6

現在、私はこの要求を持っています:

await url
    .SetQueryParams(queryString)
    .SetClaimsToken()
    .GetJsonAsync<T>()

Polly ( https://github.com/App-vNext/Polly ) の使用を開始して、再試行を処理し、より優れたユーザー エクスペリエンスを提供したいと考えています。たとえば、ネットワーク接続が悪いために最初の試行でユーザーに「電話を切る」ことはありません。これは私が使用しようとしていた例です:

int[] httpStatusCodesWorthRetrying = { 408, 500, 502, 503, 504 };
Policy
    .Handle<HttpException>()
    .OrResult<HttpResponse>(r => httpStatusCodesWorthRetrying.Contains(r.StatusCode))
    .WaitAndRetryAsync(new[] {
                    TimeSpan.FromSeconds(1),
                    TimeSpan.FromSeconds(2),
                    TimeSpan.FromSeconds(3)
                })
    .ExecuteAsync( await url... )

HttpResponseただし、戻り型である必要があります。私の Flurl の例からわかるように、 .Tであるにもかかわらず を返していHttpResponseます。はT、 を逆シリアル化するために使用される型StringContentです。

この最初の例は、PCL 内で使用していて、そこへの参照を取得できないため、まったく機能しませんSystem.Web。だから私はこれを試しました:

Policy
    .HandleResult(HttpStatusCode.InternalServerError)
    .OrResult(HttpStatusCode.BadGateway)
    .OrResult(HttpStatusCode.BadRequest)
    .WaitAndRetryAsync(new[] {
        TimeSpan.FromSeconds(1),
        TimeSpan.FromSeconds(2),
        TimeSpan.FromSeconds(3)
    })
    .ExecuteAsync(async () =>
    {
        await url...
    });

HttpStatusCodeただし、Polly は戻り値の型を想定しているため、これも機能しません。だから私の質問は次のとおりです: polly にこれらHttpStatusCodeの s を処理し、 type の戻りを許可するように指示するにはどうすればよいTですか?

4

3 に答える 3

10

Polly は、ポリシーを通じて実行されたデリゲートによって返された値をエラーとして解釈できます。ただし、あなたが観察したように.GetJsonAsync<T>()、投稿された例での呼び出し:

await url
    .SetQueryParams(queryString)
    .SetClaimsToken()
    .GetJsonAsync<T>()

返品中Tです。呼び出しはHttpResponseMessage、Json への逆シリアル化に直接進むことで非表示になりTます。

flurl で何かを返すオーバーロードを使用する必要がありますHttpResponseMessage。私は flurl を使用したことがありませんが、このオーバーロードの戻りTask<HttpResponseMessage>は有望に見えます。おそらく次のようなことができます:

List<int> httpStatusCodesWorthRetrying = new List<int>(new[] {408, 500, 502, 503, 504});
HttpResponseMessage response = await Policy
    .Handle<HttpRequestException>() 
    .Or<OtherExceptions>() // add other exceptions if you find your call may throw them, eg FlurlHttpException
    .OrResult<HttpResponseMessage>(r => httpStatusCodesWorthRetrying.Contains((int)r.StatusCode))
    .WaitAndRetryAsync(new[] {
                    TimeSpan.FromSeconds(1),
                    TimeSpan.FromSeconds(2),
                    TimeSpan.FromSeconds(3)
                })
    .ExecuteAsync(() => 
       url
        .SetQueryParams(queryString)
        .SetClaimsToken()
        .GetAsync()
    );

T responseAsT = await Task.FromResult(response).ReceiveJson<T>();

最後の への呼び出しは、元の呼び出しhere.ReceiveJson<T>()の flurl ソース コードと置換されたhereを単純に比較することをお勧めします。.GetJsonAsync<T>() .GetAsync();

もちろん、すべてを flurl の簡潔な拡張ヘルパー メソッドにラップすることもできます。おそらく次のようになります。

async T GetJsonAsyncResiliently<T>(this IFlurlClient client, Policy policy) // OR (if preferred): this Url url instead of IFlurlClient client
{
    return await Task.FromResult(policy.ExecuteAsync(() => client.GetAsync())).ReceiveJson<T>();
}

編集: のメソッドを指す際に、あなたのケースの間違った flurl オーバーロードを指摘した可能性がありますIFlurlClient。ただし、拡張メソッドの並列セットが flurl onUrlおよび内に存在するstringため、同じ原則が適用されます。

于 2016-11-22T18:36:20.220 に答える
3

HttpClientFactoryPolly で構成できる を設定して Flurl を構成し、カスタムを作成しHttpClientFactoryます。

public class MyCustomHttpClientFactory : DefaultHttpClientFactory, IMyCustomHttpClientFactory
{
    private readonly HttpClient _httpClient;
    public MyCustomHttpClientFactory(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }
    public override HttpClient CreateHttpClient(HttpMessageHandler handler)
    {
        return _httpClient;
    }
}

そのサービスを次のように登録しますConfigureServices

public void ConfigureServices(IServiceCollection services)
{
    services
        .AddHttpClient<IMyCustomHttpClientFactory, MyCustomHttpClientFactory>()
        .SetHandlerLifetime(...)
        .AddPolicyHandler(....);
}

その Factory を Flurl に割り当てます。

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // Get HttpClientFactory and Configure Flurl to use it.
    var factory = (IMyCustomHttpClientFactory)app.ApplicationServices.GetService(typeof(IMyCustomHttpClientFactory));
    FlurlHttp.Configure((settings) => settings.HttpClientFactory = factory);
}
于 2018-09-11T11:53:35.463 に答える