私たちは 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から、 を使用するオーバーロードの 1 つのサポートを実装する必要があることがわかりました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