diff --git a/src/Dodo.HttpClient.ResiliencePolicies/PoliciesHttpClientBuilderExtensions.cs b/src/Dodo.HttpClient.ResiliencePolicies/PoliciesHttpClientBuilderExtensions.cs index 598e5c5..3161819 100644 --- a/src/Dodo.HttpClient.ResiliencePolicies/PoliciesHttpClientBuilderExtensions.cs +++ b/src/Dodo.HttpClient.ResiliencePolicies/PoliciesHttpClientBuilderExtensions.cs @@ -44,6 +44,17 @@ public static IHttpClientBuilder AddResiliencePolicies( .AddTimeoutPolicy(settings.TimeoutPerTry); } + public static IHttpClientBuilder AddResiliencePolicies( + this IHttpClientBuilder clientBuilder, + Func configure) + { + return clientBuilder + .AddTimeoutPolicy(sp => configure(sp).OverallTimeout) + .AddRetryPolicy(sp => configure(sp).RetryPolicySettings) + .AddCircuitBreakerPolicy(sp => configure(sp).CircuitBreakerPolicySettings) + .AddTimeoutPolicy(sp => configure(sp).TimeoutPerTry); + } + private static IHttpClientBuilder AddRetryPolicy( this IHttpClientBuilder clientBuilder, RetryPolicySettings settings) @@ -55,6 +66,17 @@ private static IHttpClientBuilder AddRetryPolicy( .WaitAndRetryAsync(settings)); } + private static IHttpClientBuilder AddRetryPolicy( + this IHttpClientBuilder clientBuilder, + Func configure) + { + return clientBuilder + .AddPolicyHandler((sp, _) => HttpPolicyExtensions + .HandleTransientHttpError() + .Or() + .WaitAndRetryAsync(configure(sp))); + } + private static IHttpClientBuilder AddCircuitBreakerPolicy( this IHttpClientBuilder clientBuilder, CircuitBreakerPolicySettings settings) @@ -73,6 +95,24 @@ private static IHttpClientBuilder AddCircuitBreakerPolicy( }); } + private static IHttpClientBuilder AddCircuitBreakerPolicy( + this IHttpClientBuilder clientBuilder, + Func configure) + { + // This implementation takes into consideration situations + // when you use the only HttpClient against different hosts. + // In this case we want to have separate CircuitBreaker metrics for each host. + // It allows us avoid situations when all requests to all hosts + // will be stopped by CircuitBreaker due to single host is not available. + var registry = new PolicyRegistry(); + return clientBuilder.AddPolicyHandler((sp, message) => + { + var policyKey = message.RequestUri.Host; + var policy = registry.GetOrAdd(policyKey, BuildCircuitBreakerPolicy(configure(sp))); + return policy; + }); + } + private static IAsyncPolicy BuildCircuitBreakerPolicy( CircuitBreakerPolicySettings settings) { @@ -89,5 +129,12 @@ private static IHttpClientBuilder AddTimeoutPolicy( { return httpClientBuilder.AddPolicyHandler(Policy.TimeoutAsync(timeout)); } + + private static IHttpClientBuilder AddTimeoutPolicy( + this IHttpClientBuilder httpClientBuilder, + Func configure) + { + return httpClientBuilder.AddPolicyHandler((sp, _) => Policy.TimeoutAsync(configure(sp))); + } } -} +} \ No newline at end of file