Мы боремся с 429 HTTP-исключениями (исходящими от SharePoint в Интернете или Microsoft Graph), и я хочу использовать Polly и Castle.Windsor для этого.
Мой код (в выдержках)
Регистрация вещей Полли в моем контейнере Castle.Windsor:
_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
?