8

我正在实施 Polly 以在我的 C# Web 应用程序中重试请求。我的示例代码包含在这篇文章中。代码按预期工作,但传递给 CreateFile() 的最后一个参数(当前硬编码为 0)需要是 retryAttempt 的值。如何在执行操作中获取 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));
4

1 回答 1

8

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 的 execution-scoped Polly.Context: this 的一个实例随每次执行传播,并且可用于执行的所有部分。

重试策略已经将重试计数传递给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-based方法。

于 2018-12-21T07:58:32.927 回答