Flurl icon indicating copy to clipboard operation
Flurl copied to clipboard

Retry policies

Open Pinox opened this issue 6 years ago • 14 comments

Hi Guys,

Saw this on hanselman blog. freaking awesome lib.

I don't see anything in the docs like a retrycount where the httpclient can retry the request on timeout .

==> "http://localhost:7071/api/request" .RetryCount(3) //retry 3 times

or .RetryCount(3 , 300) //retry 3 times interval 300 milliseconds

Pinox avatar Jul 06 '18 10:07 Pinox

Thanks. It's a good idea and one I've thought about before. Have you checked out Polly? It's the ultimate lib for implementing retries and I recommend using it with Flurl. So I'm not sure if I want to move into that territory directly, but for a simple scenario like this I might consider it. I'll give it some thought.

tmenier avatar Jul 07 '18 15:07 tmenier

Hi @tmenier, thanks, I have seen it before but at the time when considering what I need at 272Kb file size for polly I thought it's not worth it as I will also use it in Xamarin Forms.

On the topic of third party integration , I currently use https://github.com/alexrainman/ModernHttpClient to use native methods in Android and iOS.

Is integration with such library possible with Flurl ? thanks in advance.

Pinox avatar Jul 07 '18 17:07 Pinox

https://github.com/tmenier/Flurl/issues/24 ;)

tmenier avatar Jul 07 '18 21:07 tmenier

I'm actively gathering feedback to help prioritize issues for 3.0. If this one is important to you, please vote for it here!

tmenier avatar Apr 06 '19 14:04 tmenier

I had some trouble adding policies other than using a HTTP client factory, so I wrote a nuget package call PollyFlurl to add policies in a fluent way - a bit quick and dirty, but seems to work well for my use case.

Just thought I'd share if its useful for anyone else.

Example:

"https://www.google.com/"
    .WithPolicy(
        Policy
            .Handle<HttpRequestException>()
            .OrResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
            .RetryAsync())
    .GetStringAsync();

SaahilClaypool avatar Jul 25 '22 01:07 SaahilClaypool

@tmenier I just noticed that you removed this issue from the 4.0 plan. Is there a recommended way how to combine Flurl.Http and Polly right now (either in Flurl 3.x or 4.0)? Some time ago I've researched the best way to do this. There were many options and it was hard to understand the differences.

cremor avatar Nov 24 '23 07:11 cremor

@cremor I don't really have any official recommendations, unless you can be more specific. It's been discussed on Stack Overflow, you might want to start there. Or take a look at what @SaahilClaypool mentioned above.

tmenier avatar Nov 24 '23 17:11 tmenier

I'd like to have a global Polly configuration and then use Flurl "like normal" (e.g. with string extension methods or by getting an IFlurlClientFactory injected). The Flurl client should then automatically use the Polly configuration. It looks like this is not supported by the package from @SaahilClaypool

cremor avatar Nov 26 '23 08:11 cremor

@cremor Please ask questions like that on Stack Overflow. This issue is for tracking a feature request. Thanks.

tmenier avatar Dec 02 '23 23:12 tmenier

@cremor I think i am replying on the wrong thread for this, but I have had a similar issue, as per @tmenier's reply on https://stackoverflow.com/questions/52272374/set-a-default-polly-policy-with-flurl in v3.x you would override the Factory, which added the desired functionality. however the use of factories have been removed for v4, but the ability to register a DelegatingHandler directly has been provided as middleware, which I mean is what it is.

so the solution to get a similar response is

public class PollyHandler : DelegatingHandler
{
    private readonly IAsyncPolicy<HttpResponseMessage> _policy;

    public PollyHandler(IAsyncPolicy<HttpResponseMessage> policy) {
        _policy = policy;
    }

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
        return _policy.ExecuteAsync(ct => base.SendAsync(request, ct), cancellationToken);
    }
}

and then once on startup you call:

var policy = Policy
    .Handle<HttpRequestException>()
    .OrResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
    .RetryAsync(5);
FlurlHttp.Clients.WithDefaults(clientBuilder => clientBuilder.AddMiddleware(() => new PollyHandler (policy)));

I wouldn't confidently say this is the preferred way to achieve the desired outcome, but it seems to be equivalent to the way outlined in stack overflow for v3

ZandreBroodryk avatar Dec 09 '23 13:12 ZandreBroodryk

@ZandreBroodryk Well done, I think that approach is perfect. You might not even need to write your own handler, I think you could just use this one? https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.http.policyhttpmessagehandler

That's what practically all of MS's Polly extension methods do: https://github.com/dotnet/aspnetcore/blob/main/src/HttpClientFactory/Polly/src/DependencyInjection/PollyHttpClientBuilderExtensions.cs

tmenier avatar Dec 09 '23 14:12 tmenier

[Moving this feature request to here]

Flurl and Flurl.Http are an awesome combo. Unfortunately they are currently incompatible with Polly v8 for implementing retry/resilience logic.

The Flurl.Http AddMiddleware() method works great with Polly v7 but is incompatible with Polly v8.

The issue is that Polly v8 doesn't provide a DelegatingHandler. So I guess this more of a Polly v8 issue than a Flurl.Http issue.

This Sundry.Extensions.Http.Polly seems to get pretty close on how to setup a DelegatingHandler. Refer to the PollyStrategyHttpMessageHandler.cs

Here is a post on StackOverlow with a workaround for getting Flurl.Http to work with Polly v8.

Thank you again for a great library!

jassent avatar Dec 18 '23 00:12 jassent

This API #proposal for Microsoft.Extensions.Http.Resilience would probably also benefit the Flurl.Http AddMiddleware() method.

jassent avatar Dec 19 '23 23:12 jassent

@jassent

This https://github.com/dotnet/extensions/issues/4759 for Microsoft.Extensions.Http.Resilience would probably also benefit the Flurl.Http AddMiddleware() method.

Agreed, and it sounds like they're open to hearing about real-world use cases. Maybe you could voice this one! :)

tmenier avatar Dec 20 '23 02:12 tmenier