我有以下代码:
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
链接在一起
- Polly将您的
- 如果超时触发并且所有先前的重试尝试都返回
SystemError
,则ExecuteAsync
将抛出TimeoutRejectedException