Search code examples
c#pollyretry-logic

What's alternative of HttpPolicyExtensions.HandleTransientHttpError in new Polly version?


I am trying to upgrade Polly to v8, re-writing policies to utilize new ResiliencePipiline. At couple of places I am using HttpPolicyExtensions.HandleTransientHttpError()

 HttpPolicyExtensions
                .HandleTransientHttpError()
                .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));

Looking at the source code I've endup with something like this:

ResiliencePipelineBuilder<HttpResponseMessage>()
            .AddRetry(new RetryStrategyOptions<HttpResponseMessage>()
            {
                ShouldHandle = new PredicateBuilder<HttpResponseMessage>()
                    .Handle<HttpRequestException>()
                    .HandleResult(response => response.StatusCode >= HttpStatusCode.InternalServerError || response.StatusCode == HttpStatusCode.RequestTimeout),
                MaxRetryAttempts = 3,
                DelayGenerator = static opt => ValueTask.FromResult((TimeSpan?)TimeSpan.FromSeconds(Math.Pow(2, opt.AttemptNumber)))
            })
            .Build();

Solution

  • Yes, that looks good. If you want to have a bit more performant version then you can use switch expression instead of PredicateBuilder

    var options = new RetryStrategyOptions<HttpResponseMessage>
    {
        ShouldHandle = static args => args.Outcome switch
        {
            { Exception: HttpRequestException } => PredicateResult.True(),
            { Result.StatusCode: HttpStatusCode.RequestTimeout} => PredicateResult.True(),
            { Result.StatusCode: >= HttpStatusCode.InternalServerError } => PredicateResult.True(),
            _ => PredicateResult.False()
        }
    };
    

    Please also note here the usage of static anonymous functions.


    Update #1

    This could be easily extracted into a util method to embrace reusablity.

    public static class PollyUtils
    {
      public static ValueTask<bool> HandleTransientHttpError(
        Outcome<HttpResponseMessage> outcome)
        => outcome switch
        {
            { Exception: HttpRequestException } => PredicateResult.True(),
            { Result.StatusCode: HttpStatusCode.RequestTimeout} => PredicateResult.True(),
            { Result.StatusCode: >= HttpStatusCode.InternalServerError } => PredicateResult.True(),
            _ => PredicateResult.False()
        };
    }