I have the following client app
services
.AddHttpClient<IOrderService, OrderService>(c =>
{
c.BaseAddress = new Uri(Configuration["ApiSettings:xxx"]);
})
.AddPolicyHandler(GetRetryPolicy())
private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
return
HttpPolicyExtensions
.HandleTransientHttpError()
.WaitAndRetryAsync(
retryCount: 3,
sleepDurationProvider: currNthRetry => TimeSpan.FromSeconds(Math.Pow(2, currNthRetry)),
onRetry: (Exception, retryCount, context) =>
{
// ...
});
}
so when the server is down/off, my client app is just hung, polly doesn't apply retry policy, I think it is because Polly expects to receive http status code of 408 Request Timeout first, then it can retry, but the server is down, the server cannot generate 408 error code and sent it back to the for sure. so how can I set the default timeout for Polly?
I was trying to set timeout in HttpClient
as:
services
.AddHttpClient<IOrderService, OrderService>(c =>
{
// ...
c.Timeout = TimeSpan.FromSeconds(5);
})
// ...
but it doesn't work, all I got is a TaskCanceledException
as below picture shows:
and Polly still doesn't do any retry.
So how can I return a 408 status code for Polly to consume?
I want the client app to retry a request every 5 seconds for 3 times only, that's all. The problem I have is, the server cannot return 5XX or 4XX to the client since the server is down. so the HttpClient needs to generate 408 for Polly
If your server is down and you can't get a response from it then you would either receive an HttpRequestException
or you can have a 5 seconds timeout per request.
The former case is handled by the HandleTransientHttpError
since it handles HttpRequestException
, Http status codes >= 500 (server errors) and status code 408 (request timeout).
The latter case can be achieved by combining/chaining two policies.
IAsyncPolicy<HttpResponseMessage> GetPolicy()
{
var timeout = Policy
.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromSeconds(5));
var retry = HttpPolicyExtensions
.HandleTransientHttpError()
.Or<TimeoutRejectedException>()
.WaitAndRetryAsync(
retryCount: 3,
sleepDurationProvider: _ => TimeSpan.FromSeconds(Math.Pow(2, _)));
return Policy.WrapAsync(retry, timeout);
}
.Or<TimeoutRejectedException>()
)