App-vNext / Polly

Polly is a .NET resilience and transient-fault-handling library that allows developers to express policies such as Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback in a fluent and thread-safe manner. From version 6.0.1, Polly targets .NET Standard 1.1 and 2.0+.

Home Page:https://www.thepollyproject.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Question]: Polly v8 AddPolicyHandler

mateusz-jarazny opened this issue · comments

What are you wanting to achieve?

I'm trying to implement different policies based on the request URI using the same HttpClient. Previously, I managed this by using the AddPolicyHandler function and its HttpRequestMessage parameter. However, in the new API, I can't find a similar example. Is there any way to get access to the HttpRequestMessage when defining pipeline?

What code or approach do you have so far?

.AddPolicyHandler((serviceProvider, request) =>
    request.RequestUri.PathAndQuery.StartsWith("/api/")
        ? Policy<HttpResponseMessage>.HandleResult(result => !result.IsSuccessStatusCode).WaitAndRetryAsync(3, _ => TimeSpan.FromSeconds(1))
        : HttpPolicyExtensions.HandleTransientHttpError().WaitAndRetryAsync(3, _ => TimeSpan.FromSeconds(1));

Additional context

No response

As far as I know the new AddResilienceHandler does not support this use case.

cc: @martintmk or does it?

@mateusz-jarazny

You can do something akin to following to allow dynamically changing the pipeline:

var services = new ServiceCollection();

services.AddResiliencePipeline<string, HttpResponseMessage>("pipeline-a", builder =>
{
    // ...
});

services.AddResiliencePipeline<string, HttpResponseMessage>("pipeline-b", builder =>
{
    // ...
});


var builder = services
    .AddHttpClient("my-client")
    .AddHttpMessageHandler(serviceProvider =>
    {
        var pipelineProvider = serviceProvider.GetRequiredService<ResiliencePipelineProvider<string>>();

        return new ResilienceHandler(request =>
        {
            var pipelineName = ExtractPipelineName(request);

            if ( pipelineProvider.TryGetPipeline<HttpResponseMessage>(pipelineName, out var pipeline))
            {
                return pipeline;
            }

            return ResiliencePipeline<HttpResponseMessage>.Empty;
        });
    });

The key is to create explicit instance of ResilienceHandler that allows selecting the resilience pipeline manually.

cc @peter-csala

Thank you @martintmk, it worked!
Closing the issue but maybe the example with AddHttpMessageHandler is worth adding to the documentation.