MiF*_*vil 5 c# exception-handling polly
我考虑使用 Polly 来创建记录异常和重新抛出的策略.我没有找到允许它开箱即用的现有方法,但我看到的一些选项
倒退
// Specify a substitute value or func, calling an action (eg for logging) if the fallback is invoked.
Policy.Handle<Whatever>()
.Fallback<UserAvatar>(UserAvatar.Blank, onFallback: (exception, context) =>
{ _logger.Log(exception, context);
throw exception;
});
Run Code Online (Sandbox Code Playgroud)
问题:从Fallback抛出异常是否可以?
超时
Policy.Timeout(1, T30meoutStrategy.Pessimistic, (context, timespan, task) =>
{ task.ContinueWith(t =>
{ // ContinueWith important!: the abandoned task may very well still be executing, when the caller times out on waiting for it!
if (t.IsFaulted )
{
logger.Error(context,t.Exception);
throw exception;
} );
Run Code Online (Sandbox Code Playgroud)
或者重试
Policy.Handle<DivideByZeroException>().Retry(0, (exception, retryCount) =>
{ logger.Error(context,exception);
throw exception;
} );
Run Code Online (Sandbox Code Playgroud)
问题:是否支持0次重试?
或者KISS并自己编写简单的try/catch.
哪种方法更好?你有什么建议?
mou*_*ler 12
如果你还没有混合使用Polly,那么尝试/ catch似乎最简单.
如果您已经混合使用Polly,FallbackPolicy可以按照您的建议安全地重新使用.该onFallback委托和回退操作或价值不被支配.Handle<>()的政策的条款,所以你可以安全地从内重新抛出异常onFallback委派.
Policy<UserAvatar>.Handle<Whatever>()
.Fallback<UserAvatar>(UserAvatar.Blank, onFallback: (exception, context) =>
{ _logger.Log(exception, context);
throw exception;
});
Run Code Online (Sandbox Code Playgroud)
你的问题概述的方法TimeoutPolicy只会捕获调用者之前由于超时而离开的代理抛出的异常,并且仅在TimeoutMode.Pessimistic; 并非所有例外.
您的问题概述的方法.Retry(0, ...)不起作用.如果未指定重试,则onRetry不会调用委托.
为了避免再利用的不整洁FallbackPolicy,你也可以LogThenRethrowPolicy在Polly的结构中编写自己的代码. 此提交(添加简单NoOpPolicy)举例说明了添加新策略所需的最低要求.您可以添加类似于NoOpPolicy但仅仅的实现try { } catch { /* log; rethrow */ }
编辑2019年1月:Polly.Contrib现在还包含一个Polly.Contrib.LoggingPolicy,可以帮助解决这个问题.
https://github.com/App-vNext/Polly-Samples/blob/master/PollyDemos/Async/AsyncDemo02_WaitAndRetryNTimes.cs显示您可以使用该onRetry:选项,至少对于 WaitAndRetryAsync 而言。我还没看过其他人。
HttpPolicyExtensions
.HandleTransientHttpError()
.WaitAndRetryAsync(3,
retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)) // exponential back-off: 2, 4, 8 etc
+ TimeSpan.FromMilliseconds(Jitterer.Next(0, 1000)), // plus some jitter: up to 1 second
onRetry: (response, calculatedWaitDuration) =>
{
logger.LogError($"Failed attempt. Waited for {calculatedWaitDuration}. Retrying. {response.Exception.Message} - {response.Exception.StackTrace}");
}
);
Run Code Online (Sandbox Code Playgroud)