本文介绍了如何在Flurl.Http中使用Polly?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当前我有此请求:

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

我想开始使用Polly( https://github.com/App-vNext/Polly )现在可以处理重试并提供更好的用户体验.例如,由于网络连接错误,第一次尝试时不会挂断"用户.这是我尝试使用的示例:

I'd like to start using Polly (https://github.com/App-vNext/Polly) now to handle retries and provide a better user experience. For instance, not "hanging up" on the user on the first attempt due to bad network connection. This is the example I was trying to use:

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示例中可以看到,即使它是 HttpResponse ,它也会返回 T . T 只是用于反序列化 StringContent 的类型.

But it requires HttpResponse to be the return type. As you can see from my Flurl example, it's returning T, even though it is an HttpResponse. The T is just the type used to deserialize the StringContent.

第一个示例根本不起作用,因为我在PCL中使用了该示例,因此无法在其中获得对 System.Web 的引用.所以我尝试了这个:

This first example is not working at all since I'm using it inside a PCL and I can't get a reference to System.Web there. So I tried this:

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...
    });

但是这个也不起作用,因为Polly期望 HttpStatusCode 作为返回类型.所以我的问题是:如何告诉波莉处理那些 HttpStatusCode 并仍然允许我返回 T 类型?

But this one also doesn't work because Polly expects HttpStatusCode as return type. So my question is: How can I tell polly to handle those HttpStatusCodes and still allow my return of type T?

推荐答案

Polly可以将通过策略执行的委托返回的任何值解释为错误.但是,正如您所观察到的,在您发布的示例中,对 .GetJsonAsync< T>()的调用:

Polly can interpret any value returned by a delegate executed through a policy, as a fault. However, as you observed, the call to .GetJsonAsync<T>() in your posted example:

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

正在返回 T .该调用直接进入Json反序列化为 T ,从而隐藏了 HttpResponseMessage .

is returning T. The call hides HttpResponseMessage by going straight to Json deserialization to T.

您需要在flurl中使用重载,该重载会在 HttpResponseMessage 周围返回一些内容.我没有使用flurl,但是此超载返回 Task< HttpResponseMessage> 看起来很有希望.您可能会做类似的事情:

You'd need to use an overload in flurl which returns something around HttpResponseMessage. I haven't used flurl, but this overload returning Task<HttpResponseMessage> looks promising. You could probably do something like:

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>();

建议仅在比较原始调用 .GetJsonAsync< T>()的flurl源代码时,才结束对 .ReceiveJson< T>()的调用.此处,其中用 .GetAsync(); 这里.

The call to .ReceiveJson<T>() at the end is suggested simply be comparing the flurl source code for your original call .GetJsonAsync<T>() here with the substituted .GetAsync(); here.

当然,您可以将其全部包装到flurl上的简洁扩展帮助器方法中,也许是这样的:

Of course you could wrap it all into a concise extension helper method on flurl, perhaps something like this:

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>();
}

编辑:在指向 IFlurlClient 上的方法时,我可能已经指出了错误的flurl重载.但是,在 Url string 上的flurl中存在一组并行的扩展方法,因此适用相同的原理.

EDIT: I may have pointed to the wrong flurl overloads for your case, in pointing to methods on IFlurlClient. However, a parallel set of extension methods exist within flurl on Url and string, so the same principles apply.

这篇关于如何在Flurl.Http中使用Polly?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-30 09:36