我想使用Polly执行以下操作:尝试在很短的时间内发出请求。如果失败,请重试超时。

我看到Retry可以这样访问retryCount

Policy
.Handle<SomeExceptionType>()
.Retry(3, (exception, retryCount, context) =>
{
    // do something
});


而且我看到Timeout可以指定intTimeSpan,如下所示:

Policy.Timeout(TimeSpan.FromMilliseconds(2500))


我什至看到您可以将函数传递给超时,如下所示:

Policy.Timeout(() => myTimeoutProvider)) // Func<TimeSpan> myTimeoutProvider


Func选项似乎是最有前途的,但是在哪里可以访问重试计数?将状态保留在策略之外很容易,但是如果我想以线程安全的方式共享策略,那是很危险的。

有什么建议吗?

最佳答案

您可以使用Polly Context在执行所涉及的不同策略之间传递状态数据。 Polly Context的唯一实例随每次Polly执行一起流动,因此这是完全线程安全的。

关于此技术的更多详细信息in this blog post

例如:

const string RetryCountKey = "RetryCount";

RetryPolicy retryStoringRetryCount = Policy
    .Handle<Exception>()
    .Retry(3, (exception, retryCount, context) =>
    {
        Console.WriteLine("Storing retry count of " + retryCount + " in execution context.");
        context[RetryCountKey] = retryCount;
    });

TimeoutPolicy timeoutBasedOnRetryCount = Policy
    .Timeout(context =>
    {
        int tryCount;
        try
        {
            tryCount = (int) context[RetryCountKey];
        }
        catch
        {
            tryCount = 0; // choose your own default for when it is not set; also applies to first try, before any retries
        }

        int timeoutMs = 25 * (tryCount + 1);
        Console.WriteLine("Obtained retry count of " + tryCount + " from context, thus timeout is " + timeoutMs + " ms.");
        return TimeSpan.FromMilliseconds(timeoutMs);
    });

PolicyWrap policiesTogether = retryStoringRetryCount.Wrap(timeoutBasedOnRetryCount);


(注意:当然可以使此^更加简洁。此处列出以提供最大的清晰度。)

这是live dotnetfiddle example

08-26 16:23