[API Proposal]: Resilience extensions - Expose StandardResiliencePipeline as a DelegatingHandler or ResiliencePipeline<HttpResponseMessage> in addition to the current AddStandardResilienceHandler extension method
- Dominant language
- C#
- Stars
- 3.2k
- Forks
- 894
- Avg merge
- 1d 12h
- Merged PRs (30d)
- 23
Description
### Background and motivation
### Motivation
The standard resilience pipeline is a best practice, and we would like to adopt for most of our services. However, we notice that the only way to use the standard resilience pipeline directly is through the `IHttpClientBuilder` interface. This means that before a service could start to take benefits of the resilience extension library, it has to firstly refactor all its old HttpClient initialization pattern to the `HttpClientFactory` pattern. This is bad news for legacy services who simply new `HttpClient` directly from `DelegatingHandlers`.
By encapsulating the resilience logic of the standard resilience pipeline and exposing it as a `DelegatingHandler` directly or expose a ready to use `Func>` (which can be used to initialize a `ResilienceHandler` directly) for standard resilience pipeline, we enable services that rely on long-lived `HttpClient` instances to leverage .NET Resilience Extensions. This allows them to create standard resilience pipelines and use them as `DelegatingHandler`, just like services that adopt `HttpClientFactory`.
The same to other pipelines provided by .NET resilience extension library, like standard hedging, etc.
### API Proposal
In today's .NET resilience library, there is already a [AddHttpResiliencePipeline](https://source.dot.net/#Microsoft.Extensions.Http.Resilience/Resilience/[ResilienceHttpClientBuilderExtensions.Resilience.cs](https://source.dot.net/#Microsoft.Extensions.Http.Resilience/Resilience/ResilienceHttpClientBuilderExtensions.Resilience.cs,134),134) private method, who underlying uses the Polly's [IServiceCollection.AddResiliencePipeline](https://www.pollydocs.org/advanced/dependency-injection#usage) method.
We can add a similar API `IServiceCollection.AddStandardResiliencePipeline` in .NET resilience extension library.
```csharp
public static IHttpStandardResiliencePipelineBuilder AddStandardResiliencePipeline(this IServiceCollection services, string name)
{
var pipelineName = name;
var key = new HttpKey(pipelineName, string.Empty);
_ = services.AddResiliencePipeline(key, (builder, context) => {
var resilienceHandlerContext = new ResilienceHandlerContext(context);
builder.AddXXX
...
do the standard resilience logic
});
ConfigureHttpServices(services);
}
```
The main purpose of goal is to encapsulate the Standard Resilience logic inside and then make it easy to use not only from `IHttpClientBuilder`, but also for other cases.
### API Usage
```csharp
var services = new ServiceCollection();
services.AddStandardResiliencePipeline("standard-resilience-pipeline");
var serviceProvider = services.BuildServiceProvider();
ResilienceHandler standardResilienceHandler = CreateResilienceHandler(CreatePipelineProvider(serviceProvider, "standard-resilience-pipeline"))
var httpClient = new HttpClient(standardResilienceHandler);
private static Func> CreatePipelineProvider(IServiceProvider serviceProvider, string pipelineName)
{
_ = Throws.IfNull(serviceProvider);
_ = Throws.IfNullOrEmpty(pipelineName);
string pipelineName2 = pipelineName;
ResiliencePipelineProvider resilienceProvider = serviceProvider.GetRequiredService>();
ResiliencePipeline pipeline = resilienceProvider.GetPipeline(pipelineName2);
return (request) => pipeline;
}
private static ResilienceHandler CreateResilienceHandler(Func> pipelineProvider) =>
new ResilienceHandler(pipelineProvider);
```
### Alternative Designs
Another acceptable way is to instead of exposing the standard resilience pipeline as a Polly Resilience Pipeline, it's also ok to expose it as a ready to use `DelegatingHandler`.
### Risks
Since this is asking to add new features without having to change existing code, so should have less risks.
Contributor guide
Assessment
This issue has not been assessed yet.