// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Threading; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Http.Resilience; using Microsoft.Extensions.Http.Resilience.Internal; using Microsoft.Extensions.Http.Resilience.Internal.Validators; using Microsoft.Extensions.Options; using Microsoft.Shared.Diagnostics; using Polly; namespace Microsoft.Extensions.DependencyInjection; public static partial class ResilienceHttpClientBuilderExtensions { private const string StandardIdentifier = "standard"; /// /// Adds a standard resilience handler that uses multiple resilience strategies with default options to send the requests and handle any transient errors. /// /// The builder instance. /// The section that the options will bind against. /// The value of . /// /// The resilience pipeline combines multiple strategies that are configured based on HTTP-specific options with recommended defaults. /// See for more details about the individual resilience strategies configured by this method. /// public static IHttpStandardResiliencePipelineBuilder AddStandardResilienceHandler(this IHttpClientBuilder builder, IConfigurationSection section) { _ = Throw.IfNull(builder); _ = Throw.IfNull(section); return builder.AddStandardResilienceHandler().Configure(section); } /// /// Adds a standard resilience handler that uses multiple resilience strategies with default options to send the requests and handle any transient errors. /// /// The builder instance. /// The callback that configures the options. /// The value of . /// /// The resilience pipeline combines multiple strategies that are configured based on HTTP-specific options with recommended defaults. /// See for more details about the individual resilience strategies configured by this method. /// public static IHttpStandardResiliencePipelineBuilder AddStandardResilienceHandler(this IHttpClientBuilder builder, Action configure) { _ = Throw.IfNull(builder); _ = Throw.IfNull(configure); return builder.AddStandardResilienceHandler().Configure(configure); } /// /// Adds a standard resilience handler that uses multiple resilience strategies with default options to send the requests and handle any transient errors. /// /// The builder instance. /// The value of . /// /// The resilience pipeline combines multiple strategies that are configured based on HTTP-specific options with recommended defaults. /// See for more details about the individual resilience strategies configured by this method. /// public static IHttpStandardResiliencePipelineBuilder AddStandardResilienceHandler(this IHttpClientBuilder builder) { _ = Throw.IfNull(builder); var optionsName = PipelineNameHelper.GetName(builder.Name, StandardIdentifier); _ = builder.Services.AddOptionsWithValidateOnStart(optionsName); _ = builder.Services.AddOptionsWithValidateOnStart(optionsName); _ = builder.AddResilienceHandler(StandardIdentifier, (builder, context) => { context.EnableReloads(optionsName); var monitor = context.ServiceProvider.GetRequiredService>(); var options = monitor.Get(optionsName); _ = builder .AddRateLimiter(options.RateLimiter) .AddTimeout(options.TotalRequestTimeout) .AddRetry(options.Retry) .AddCircuitBreaker(options.CircuitBreaker) .AddTimeout(options.AttemptTimeout); }); // Disable the HttpClient timeout to allow the timeout strategies to control the timeout. _ = builder.ConfigureHttpClient(client => client.Timeout = Timeout.InfiniteTimeSpan); return new HttpStandardResiliencePipelineBuilder(optionsName, builder.Services); } private sealed record HttpStandardResiliencePipelineBuilder(string PipelineName, IServiceCollection Services) : IHttpStandardResiliencePipelineBuilder; }