Reputation: 23
We have a vendor that goes down a lot. We no longer want the circuit to break when they pass us back 500 errors, etc.. We just want the circuit to break when there is a Timeout Exception.
IAsyncPolicy<HttpResponseMessage> circuitBreaker = HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(msg => msg.StatusCode == HttpStatusCode.RequestTimeout)
.AdvancedCircuitBreakerAsync(
failureThreshold: 0.25,
samplingDuration: TimeSpan.FromSeconds(300),
minimumThroughput: 50,
durationOfBreak: TimeSpan.FromSeconds(20));
services.AddHttpClient<IFinancialDetailsService, FinancialDetailsService>()
.AddPolicyHandler(circuitBreaker);
How can I do this via Polly? HandleTransientHttpError
handles 5XX and 408 errors, but I don't see any other extension methods besides that and OrTransientHttpError
which does the same thing.
Upvotes: -1
Views: 87
Reputation: 22829
The HandleTransientHttpError
handles 408, 5XX status codes and HttpRequestException
. It is important to understand that HttpClient
does not throw TimeoutException
directly. Rather than it is wrapped inside a TaskCanceledException
since .NET 5:
try
{
var response = await client.GetAsync(downstreamServiceUrl);
}
catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException)
{
...
}
For earlier .NET versions you have to examine the CancellationTokenSource
to determine whether is it a cancelled or a timed out request.
var cts = new CancellationTokenSource();
try
{
var response = await client.GetAsync(downstreamServiceUrl, cts.Token);
}
catch (TaskCanceledException ex) when (!cts.IsCancellationRequested)
{
...
}
So, if you are using .NET 5 or above you have to add the following clause to your policy builder (before the .AdvanceCircuitBreakerAsync
):
.Or<TaskCanceledException>(ex => ex.InnerException is TimeoutException)
If you are using earlier .NET version then:
.Or<TaskCanceledException>(_ => !cts.IsCancellationRequested)
Update #1
If you want to handle only timeout scenarios then you don't need to use the HttpPolicyExtensions.HandleTransientHttpError()
method. Rather than you can define your policy simply like this:
IAsyncPolicy<HttpResponseMessage> circuitBreaker = Policy<HttpResponseMessage>
.Handle<TaskCanceledException>(ex => ex.InnerException is TimeoutException)
.AdvancedCircuitBreakerAsync(...
OR
IAsyncPolicy<HttpResponseMessage> circuitBreaker = Policy<HttpResponseMessage>
.Handle<TaskCanceledException>(_ => !cts.IsCancellationRequested)
.AdvancedCircuitBreakerAsync(...
Upvotes: 0