使用Castle.Windsor和Polly响应429个异常(限制)

问题描述 投票:0回答:1

[我们正在处理429个HTTP异常(来自SharePoint Online或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"));

我的波莉的东西:

 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标头的支持。

我从此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 ;-)
}

想法是,我将仅查看服务器响应的标头,并将时间跨度传递回sleepDurationProvider

但是-从配置sleepDurationProvider的行中出现错误。有人告诉我(retryCount, response)是“不兼容的匿名函数签名”

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

c# castle-windsor throttling polly
1个回答
0
投票

您可能会像这样查看标题

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
                );
        }
© www.soinside.com 2019 - 2024. All rights reserved.