c# - 使用 CaSTLe.Windsor 和 Polly 响应 429 异常( throttle )

标签 c# castle-windsor throttling polly

我们正在努力处理 429 HTTP 异常(来自 SharePoint 在线或 Microsoft Graph),我想利用 Polly 和 CaSTLe.Windsor 来处理这个问题。

我的代码是(摘录)

在我的 CaSTLe.Windsor 容器中注册 Polly 内容:

_container.Register(Component.For<IRepository>()
            .ImplementedBy<Repository>()
            .DependsOn(Dependency.OnValue<ImportSettings>(_importSettings))
            .Interceptors(InterceptorReference.ForKey("throttle")).Anywhere
            .LifestyleTransient());

 _container.Register(Component.For<WaitAndRetryInterceptor<WebException>>().LifeStyle.Singleton
    .Named("throttle"));

我的 Polly 东西:

 public class WaitAndRetryInterceptor<T> : IInterceptor where T : WebException
    {
        private readonly RetryPolicy _policy;

        public void Intercept(IInvocation invocation)
        {
            var dictionary = new Dictionary<string, object> {{"methodName", invocation.Method.Name}};

            _policy.Execute(invocation.Proceed, dictionary);
        }

        public WaitAndRetryInterceptor()
        {
            _policy =
                Policy
                    .Handle<T>()
                    .WaitAndRetry(new[]
                    {
                        TimeSpan.FromSeconds(16), TimeSpan.FromSeconds(32), TimeSpan.FromSeconds(64),
                        TimeSpan.FromSeconds(128), TimeSpan.FromSeconds(256), TimeSpan.FromSeconds(512)
                    });
        }
    }

所以这个实现满足了我的需要——但它过于保守了。因此,我尝试实现对抛出的 429 异常的直接支持 - 特别是对服务器可用的 Reply-After header 的支持。

我从这个https://github.com/App-vNext/Polly/issues/414中发现,我需要实现对采用 sleepDurationProvider 的重载之一的支持,但我在正确编写代码时遇到了问题。

我的实现是这样的:

_policy =
  Policy
    .Handle<HttpRequestException>()
    .OrResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.Accepted) //needs to be changed to 429
    .WaitAndRetryAsync(
        retryCount: 3,
        sleepDurationProvider: (retryCount, response) =>
        {
            return getServerWaitDuration(response);
        })
;

getServerWaitDuration只是返回一个TimeSpan

private TimeSpan getServerWaitDuration(DelegateResult<HttpResponseMessage> response)
{
    return TimeSpan.Zero;  //not actual code ;-)
}

我的想法是,我将简单地查看来自服务器的响应的 header ,并将时间跨度传回给 sleepDurationProvider

但是 - 我在配置 sleepDurationProvider 的行中收到错误。我被告知 (retryCount, response) 是一个“不兼容的匿名函数签名”

我觉得我在这里遗漏了一些明显的东西。但为什么?如何访问 response 对象以提取 Retry-After 持续时间?

最佳答案

你可能会像这样查看标题

public AsyncRetryPolicy<HttpResponseMessage> GetRetryPolicy()
        {
            return HttpPolicyExtensions
                .HandleTransientHttpError()
                .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
                .OrResult(r =>  r?.Headers?.RetryAfter != null)
                .WaitAndRetryAsync(
                    3,
                    sleepDurationProvider: (retryCount, response, context) =>
                    {
                        return response.Result.Headers.RetryAfter.Delta.Value;
                    },
                    onRetryAsync: (e, ts, i, ctx) => Task.CompletedTask
                );
        }

关于c# - 使用 CaSTLe.Windsor 和 Polly 响应 429 异常( throttle ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58660200/

相关文章:

javascript - WebBrowser 中具有 Doctype 的不同 JavaScript 行为

c# - SSH.Net隧道

javascript - underscore.js 的 throttle 实现中的 'remaining > wait' 条件语句何时为真?

javascript - 如何在 React 功能组件中限制 onWheel 事件

laravel - 如何实现 Laravel Redis 速率限制

c# - 如何对私有(private)属性进行单元测试?

c# - 为什么同步延续不再同步执行?

asp.net-mvc - 使用 CaSTLe Windsor 在 ASP.NET MVC 中设置控制反转 (IoC)

c# - 使用 ASP MVC 和 CaSTLe Windsor 将数据库注入(inject)验证属性

dependency-injection - CaSTLe Windsor 带泛型的类型化工厂设施