如何通过Polly重试策略获得委托中的重试计数?

时间:2018-12-20 23:49:59

标签: c# polly retry-logic

我正在实现Polly以在C#Web应用程序中重试请求。我的示例代码包含在这篇文章中。该代码可以按预期工作,但是传递给CreateFile()的最后一个参数(当前硬编码为0)需要为retryAttempt的值。如何在Execute Action中获取retryAttempt的值?

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, 0));

1 个答案:

答案 0 :(得分:0)

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,该使用基于Context的方法。