polly在给定时间段内重试策略



我有以下代码:

var expirationPeriodMilliseconds = 1000;
return Policy
.HandleResult<EnquiryResult>(message => message.Status == EnquiryStatus.SystemError)
.RetryForeverAsync() // instead run until expirationPeriodMilliseconds
.ExecuteAsync(async () => await ratingProvider.Enquire(request, cancellationToken));

有什么解决方案可以让polly在一段时间内使用重试选项吗?

尽管这是一个稍后的答案,但它可能对未来的读者有帮助

政策定义

var globalTimeoutPolicy = Policy
.TimeoutAsync<EnquiryResult>(TimeSpan.FromMilliseconds(expirationPeriodMilliseconds));
var retryForeverPolicy = Policy
.HandleResult<EnquiryResult>(message => message.Status == EnquiryStatus.SystemError)
.RetryForeverAsync();
var combinedPolicy = Policy.WrapAsync(globalTimeoutPolicy, retryForeverPolicy);
  • 这里我们定义了两个策略
    • 一个用于在收到SystemError时反复重试相同操作的
    • 另一个在N毫秒后终止操作
  • 最后,我们将这些政策结合在一起
    • 因为globalTimeoutPolicy已首先传递给WrapAsync,这就是它是外部策略的原因,所以此超时会遍历所有重试尝试
    • 如果我们将globalTimeoutPolicy作为WrapAsync的第二个参数传递,那么这个超时约束将适用于每个单独的重试尝试

链式策略的使用

try
{
var result = await combinedPolicy.ExecuteAsync(
async (ct) => await ratingProvider.Enquire(request, ct), cancellationToken);
Console.WriteLine($"Method has successfully completed with status: '{result.Status}'.");
}
catch(TimeoutRejectedException)
{
Console.WriteLine($"Method has failed after retrying for {expirationPeriodMilliseconds}ms.");
}
  • 因为您的ratingProvider.Enquire方法预计会出现CancellationToken,所以我们可以使用乐观超时策略
    • Polly将您的cancellationToken与超时策略的CancellationToken链接在一起
  • 如果超时触发并且所有先前的重试尝试都返回SystemError,则ExecuteAsync将抛出TimeoutRejectedException

最新更新