简体   繁体   English

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

[英]How can I get the retry count within a delegate executed through Polly retry policy?

I'm implementing Polly to retry requests in my C# web app. 我正在实现Polly以在C#Web应用程序中重试请求。 My sample code is included in this post. 我的示例代码包含在这篇文章中。 The code works as expected but the last parameter passed to CreateFile() (currently hard-coded as 0) needs to be the value of retryAttempt. 该代码可以按预期工作,但是传递给CreateFile()的最后一个参数(当前硬编码为0)需要为retryAttempt的值。 How can I get the value of retryAttempt within the Execute Action? 如何在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));

Polly does not provide an .Execute(...) overload where retry count is one of the input parameters to the delegate passed to .Execute(...) . Polly不提供.Execute(...)重载,其中重试计数是传递给.Execute(...)的委托的输入参数之一。 This is because retry is only one of many Polly policies, whereas the shape of .Execute(...) overloads must be general to all policy types. 这是因为重试仅是许多Polly策略之一,而.Execute(...)重载的形式对于所有策略类型必须是通用的。

For the use case described in the question, simply: 对于问题中描述的用例,只需:

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++));

An alternative approach uses Polly's execution-scoped Polly.Context : an instance of this travels with each execution, and is available to all parts of an execution. 另一种方法是使用Polly的执行范围的Polly.Context :此实例随每次执行一起传播,并且可用于执行的所有部分。

Retry policy already passes the retry count to the onRetry delegate, so the policy can capture this into the execution-scoped 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;
            });

In the delegate executed through the policy, we can pick the retry count out of Context (taking care to handle the case when no retries have yet happened): 在通过策略执行的委托中,我们可以从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());

If you prefer to avoid the noise of the context.TryGetValue(...) defensive code, you can alternatively choose to ensure you always initialise context["retrycount"] before you start an execution: 如果您希望避免使用context.TryGetValue(...)防御性代码,可以选择确保在执行之前始终初始化context["retrycount"]

var myContext = new Polly.Context { {"retrycount ", 0} };
retryPolicyCapturingCountIntoContext
    .Execute(
         context => CreateFile(fileContent, containerName, fileName, connectionString, (int)context["retrycount"]),
         myContext);


For users who want to capture the retry count of each retry as it happens, say for logging, see the Polly retry examples showing how retryCount is passed as an input parameter to the onRetry delegate which can be configured on the policy. 对于想要捕获每次重试发生时的重试计数(例如进行记录)的用户,请参阅Polly重试示例 ,该示例显示了retryCount如何作为输入参数传递给可以在策略上配置的onRetry委托。 Further examples here . 这里有更多示例。

For users who want to capture the overall number of retries used for an operation to succeed, in a generalised way - say for telemetry as part of some general execution-dispatch infrastructure code - see these examples in Steve Gordon's blog , which use the Context -based approach. 对于希望以通用方式捕获用于成功完成操作的重试总数的用户(例如,将遥测作为某些通用执行调度基础结构代码的一部分),请参阅Steve Gordon博客中的使用Context 这些示例 -基于方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM