Search code examples
c#asp.netpolly

How to use policy wrap on RetryPolicy<HttpResponseMessage>?


I have the following retry policy which uses Polly.Extensions.Http:

var retryPolicy = Policy.Handle<BrokenCircuitException>().OrTransientHttpError().WaitAndRetryAsync
                (
                    retryCount: maxRetryCount,
                    sleepDurationProvider: attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)),
                    onRetryAsync: (exception, calculatedWaitDuration, retryCount, context) =>
                    {
                      //Code
                    }
                );

I want to wrap the policy with circuit breaker and bulk head policies:

var circuitBreaker = Policy.Handle<HttpRequestException>().CircuitBreakerAsync(
            exceptionsAllowedBeforeBreaking: maxExceptionsBeforeBreaking,
            durationOfBreak: TimeSpan.FromSeconds(circuitBreakDurationSeconds),
            onBreak: (exception, timespan, context) =>
            {
              //Code
            },
            onReset: (context) =>
            {
                //Code
            }
        );

var sharedBulkhead = Policy.BulkheadAsync(
            maxParallelization: maxParallelizations,
            maxQueuingActions: maxQueuingActions,
            onBulkheadRejectedAsync: (context) =>
            {
                //Code
            }
        );

I use the following code to wrap the policies together:

Policy.WrapAsync(retryPolicy, circuitBreaker, sharedBulkhead);

This is giving an error:

can not convert from 'Polly.Retry.RetryPolicy<System.Net.Http.HttpResponseMessage>' to 'Polly.IAsyncPolicy'


Solution

  • When policy configuration uses .HandleTransientHttpError() or .OrTransientHttpError(), the policies are configured to handle specific status code results of an execution returning HttpResponseMessage.

    This makes the returned policies of a type which fulfils the generic interface IAsyncPolicy<HttpResponseMessage> rather than the non-generic IAsyncPolicy.

    To create a generic PolicyWrap<TResult> using the PolicyWrap static syntax you must specify the generic type parameter explicitly:

    Policy.WrapAsync<HttpResponseMessage>(retryPolicy, circuitBreaker, sharedBulkhead)
    

    If you use the PolicyWrap instance syntax, the compiler can usually infer the syntax. So the following should also be sufficient:

    retryPolicy.WrapAsync(circuitBreaker).WrapAsync(sharedBulkhead)
    

    Polly documentation covers the differences between non-generic and generic policies, in general, in the readme and wiki.