Polly没有提供一个重试次数是委托参数之一的.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重试示例,其中展示了如何将
retryCount
作为输入参数传递给可以在策略上配置的
onRetry
委托。更多示例请参见
此处。
对于想要以一种通用的方式捕获操作使用的总重试次数以便成功,例如用于某些常规执行-调度基础架构代码的遥测,请参阅
Steve Gordon博客中的这些示例,这些示例使用基于
Context
的方法。