Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retry multiple times when http request times out using polly c#

My original intention was to retry multiple times when the request itself times out, such as when trying to communicate to another micro service which is down for a couple of seconds in the hope it is a temporary failure. If there is a simpler solution to do just that it would suffice. I decided to manually set timeout per retry using a wrapping policy, hoping to achieve the same result.

I've seen a similar solution not using httpclientfactory here Use a specific timeout connected to a retrypolicy, but it doesn't work for me.

My code looks like this:

services.AddHttpClient("retryclient", client =>
{
    client.Timeout = TimeSpan.FromSeconds(100);
}).AddPolicyHandler((servs, request) =>
    Policy.HandleResult<HttpResponseMessage>(r =>
        {
            return r.StatusCode == HttpStatusCode.NotFound; //(1)
        }).
.OrTransiesntHttpError().
WaitAndRetryAsync(5, retryAttempt => TimeSpan.FromSeconds(retryAttempt),
    onRetry: (exception, timespan, retryAttempt, context) =>
        { // using servs to log // });
}).WrapAsync(Policy.TimeoutAsync(1)));

I have checked that the retry policy works when I try to access a 'not-found' adress without wrapping the timeout policy and it works fine. I've also tried to use line (1) with the status code HttpStatusCode.RequestTimeout instead of not found for my case, but it doesn't work.

When I am using the wrapping and trying to access a service which is down it throws a Polly.Timeout.TimeoutRejectedException on the first try as I would have expected, but doesn't retry again. I couldn't figure a way to retry multiple time, either with a set timeout for each retry, or just when the request itself time outs not using a timeout policy.

Edit: After further reading https://cm.engineering/transient-timeouts-and-the-retry-rabbit-hole-net-4-5-f406cebbf194 it seems my problem is inside the policy handling I don't have access to the cancellation token of the HttpClient. I assume I can fix it by overriding the sendAsync method as shown in link. Is there an elegant way to do same while creating the factory?

like image 844
pixel Avatar asked Nov 07 '25 09:11

pixel


1 Answers

The Polly documentation on HttpClientFactory covers this in a section labelled applying timeouts:

You may want the retry policy to retry if any individual try timed out. To do this, make the retry policy handle the TimeoutRejectedException which Polly's timeout policy throws.

So:

services.AddHttpClient("retryclient", client =>
{
    client.Timeout = TimeSpan.FromSeconds(100);
}).AddPolicyHandler((servs, request) =>
    Policy.HandleResult<HttpResponseMessage>(r =>
        {
            return r.StatusCode == HttpStatusCode.NotFound; //(1)
        }).
.OrTransientHttpError()
.Or<TimeoutRejectedException>() // ** ADDED **
.WaitAndRetryAsync(5, retryAttempt => TimeSpan.FromSeconds(retryAttempt),
    onRetry: (exception, timespan, retryAttempt, context) =>
        { // using servs to log // });
})
.WrapAsync(Policy.TimeoutAsync(1)));

Polly passes the CancellationToken to the internal .SendAsync() call correctly; no changes should be needed concerning that.

like image 93
mountain traveller Avatar answered Nov 10 '25 01:11

mountain traveller



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!