Polly 不提供.Execute(...) 重载,其中重试计数是传递给.Execute(...) 的委托的输入参数之一。这是因为重试只是众多 Polly 策略之一,而 .Execute(...) 重载的形式必须对所有策略类型通用。
对于问题中描述的用例,简单地说:
int count = 0;
return Policy
.Handle<HttpException>(x => x.StatusCode == (HttpStatusCode)429)
.Or<StorageException>()
.WaitAndRetry(maxRetryCount, retryAttempt => TimeSpan.FromMilliseconds(Math.Pow(retryIntervalMs, retryAttempt)))
.Execute(() => CreateFile(fileContent, containerName, fileName, connectionString, count++));
另一种方法是使用 Polly 的执行范围 Polly.Context:此实例随每次执行而传播,并且可用于执行的所有部分。
重试策略已将重试计数传递给onRetry 委托,因此该策略可以将其捕获到执行范围的Context:
var retryPolicyCapturingCountIntoContext =
Policy
.Handle<HttpException>(x => x.StatusCode == (HttpStatusCode)429)
.Or<StorageException>()
.WaitAndRetry(
maxRetryCount,
retryAttempt => TimeSpan.FromMilliseconds(Math.Pow(retryIntervalMs, retryAttempt)),
onRetry: (response, delay, retryCount, context) =>
{
context["retrycount"] = retryCount;
});
在通过策略执行的委托中,我们可以从Context中选择重试计数(注意处理尚未发生重试的情况):
retryPolicyCapturingCountIntoContext
.Execute(context =>
{
int retryCount = (context.TryGetValue("retrycount", out var retryObject) && retryObject is int count) ? count : 0;
CreateFile(fileContent, containerName, fileName, connectionString, retryCount);
}, new Context());
如果您希望避免 context.TryGetValue(...) 防御性代码的干扰,您也可以选择确保在开始执行之前始终初始化 context["retrycount"]:
var myContext = new Polly.Context { {"retrycount ", 0} };
retryPolicyCapturingCountIntoContext
.Execute(
context => CreateFile(fileContent, containerName, fileName, connectionString, (int)context["retrycount"]),
myContext);
对于想要在每次重试发生时捕获重试计数的用户,例如日志记录,请参阅Polly retry examples,其中显示了 retryCount 如何作为输入参数传递给 onRetry 委托,可以在政策。更多示例here。
对于希望以通用方式捕获用于成功操作的重试总数的用户 - 例如将遥测作为某些通用执行调度基础设施代码的一部分 - 请参阅 these examples in Steve Gordon's blog,它使用 @987654339基于@的方法。