I want to use a Polly circuit breaker policy or advanced circuit breaker policy but don't want the circuit to throw an exception when its state is open/isolated.
The idea came after reading Reducing thrown exceptions when the circuit is broken.
You will have to add the dotnet-sdk-extensions nuget to your project.
Note
the variable services
in the examples below is of type IServiceCollection
. On the default template
for a Web API you can access it via builder.services
. Example:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
You can augment the circuit breaker policy with the circuit breaker checker policy as follows:
// create the circuit breaker policy
var circuitBreakerPolicy = Policy<int>
.Handle<Exception>()
.CircuitBreakerAsync(2, TimeSpan.FromMinutes(1));
// create the circuit breaker checker policy
var circuitBreakerCheckerPolicy = CircuitBreakerCheckerAsyncPolicy.Create(
circuitBreakerPolicy: circuitBreakerPolicy,
fallbackValueFactory: (circuitState, context, cancellationToken) => Task.FromResult(-1));
// create a policy that applies both the circuit breaker checker and the circuit breaker policy
var finalPolicy = Policy.WrapAsync(circuitBreakerCheckerPolicy, circuitBreakerPolicy);
The above is just one way of using the Polly. You can integrate the circuit breaker checker policy in as many different ways as Polly provides support for. For instance you could use the PolicyRegistry to achieve a similar result.
When configuring an HttpClient for your app you can add the circuit breaker and circuit breaker checker policy by doing the following:
services
.AddHttpClient("my-http-client")
.AddHttpMessageHandler(() =>
{
var circuitBreakerPolicy = HttpPolicyExtensions
.HandleTransientHttpError()
.CircuitBreakerAsync(2, TimeSpan.FromMinutes(1));
var circuitBreakerCheckerPolicy = CircuitBreakerCheckerAsyncPolicy.Create(
circuitBreakerPolicy: circuitBreakerPolicy,
fallbackValueFactory: (circuitState, context, cancellationToken) =>
{
var response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
return Task.FromResult<HttpResponseMessage>(response);
});
var finalPolicy = Policy.WrapAsync(circuitBreakerCheckerPolicy, circuitBreakerPolicy);
return new PolicyHttpMessageHandler(finalPolicy);
})
In this example we create a wrapped policy that will first apply the circuit breaker checker policy and then the circuit breaker policy and then we add an PolicyHttpMessageHandler
to the HttpClient
that uses the wrapped policy.
var circuitBreakerPolicy = HttpPolicyExtensions
.HandleTransientHttpError()
.CircuitBreakerAsync(2, TimeSpan.FromMinutes(1));
var circuitBreakerCheckerPolicy = CircuitBreakerCheckerAsyncPolicy.Create(
circuitBreakerPolicy: circuitBreakerPolicy,
fallbackValueFactory: (circuitState, context, cancellationToken) =>
{
var response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
return Task.FromResult<HttpResponseMessage>(response);
});
var registry = new PolicyRegistry
{
{"circuit-breaker", circuitBreakerPolicy},
{"circuit-breaker-checker", circuitBreakerCheckerPolicy}
};
services.AddPolicyRegistry(registry);
services
.AddHttpClient("my-http-client")
.AddPolicyHandlerFromRegistry("circuit-breaker-checker")
.AddPolicyHandlerFromRegistry("circuit-breaker");
In this example we populate the PolicyRegistry
with the circuit breaker checker policy and the circuit breaker policy and then we configure the HttpClient
by applying the policies in the order we want.
Polly is a fantastic library and there are many ways to use it on your application. The above examples were just to show how the CircuitBreakerCheckerAsyncPolicy
could be applied.
To find out more see Polly's docs: