Reputation: 381
I am using Polly to implement request retries. However, after a 500 response is returned for a request, not only does Polly not send a request when it retries but no requests are sent at all until the process is restarted. Instead Polly just waits until there is a timeout. The following is the code:
var timeoutPolicy = TimeoutPolicy
.TimeoutAsync<HttpResponseMessage>(c => c.GetTimeout() ?? TimeSpan.FromSeconds(30)); //timeout para cada intento
var retryPolicy = HttpPolicyExtensions
.HandleTransientHttpError()
.Or<TimeoutRejectedException>() //tirado por la TimeoutPolicy
.WaitAndRetryAsync(new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10) });
var policyHandler = new PolicyHandler(Policy.WrapAsync(retryPolicy, timeoutPolicy));
How can I fix the code such that Polly actually sends the request when it retries after a 500 and also for following requests?
Upvotes: 1
Views: 1127
Reputation: 381
The error was caused by the following issue
This is how I fixed it:
var retryPolicy = HttpPolicyExtensions
.HandleTransientHttpError()
.Or<TimeoutRejectedException>() //tirado por la TimeoutPolicy
.WaitAndRetryAsync(new[]
{
TimeSpan.FromSeconds(1),
TimeSpan.FromSeconds(5),
TimeSpan.FromSeconds(10)
},
onRetry: (x, _) =>
{
//dispose response when retrying
x.Result?.Dispose();
});
Upvotes: 1
Reputation: 22819
I do believe that the application crash is not related to these policies.
I've amended your code with some debugging logs like this:
public static readonly HttpClient client = new HttpClient();
public static async Task Main(string[] args)
{
var sw = Stopwatch.StartNew();
Console.WriteLine($"{sw.Elapsed.Seconds}: Application starts");
var timeoutPolicy = TimeoutPolicy
.TimeoutAsync<HttpResponseMessage>(
TimeSpan.FromSeconds(30),
onTimeoutAsync: (ctx, ts, t) => {
Console.WriteLine($"{sw.Elapsed.Seconds}: Timeout has occurred");
return Task.CompletedTask;
});
var retryPolicy = HttpPolicyExtensions
.HandleTransientHttpError()
.Or<TimeoutRejectedException>()
.WaitAndRetryAsync(
new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10) },
onRetryAsync: (dr, ts) => {
Console.WriteLine($"{sw.Elapsed.Seconds}: Retry will be triggered");
return Task.CompletedTask;
});
var strategy = Policy.WrapAsync(retryPolicy, timeoutPolicy);
await strategy.ExecuteAsync(async (ct) => {
var response = await client.GetAsync("https://httpstat.us/500");
Console.WriteLine($"{sw.Elapsed.Seconds}: Response has been received");
return response;
}, CancellationToken.None);
Console.WriteLine($"{sw.Elapsed.Seconds}: Application finishes");
}
Response has been received
whenever the httpClient has received a response
httpstat.us
only for testing purposesTimeout has occurred
whenever the httpClient did not receive a response under 30 secondsRetry will be triggered
whenever the retry policy should be fired but before the delay penaltyApplication finishes
whenever all the retries are issued and none of them succeeded or when one of the requests succeedsWith the current setup the output would look like this:
1: Response has been received
1: Retry will be triggered
2: Response has been received
2: Retry will be triggered
8: Response has been received
8: Retry will be triggered
18: Response has been received
18: Application finishes
So as you can see, we have issued 4 requests (one initial and 3 retries) without luck. But at the end the application has continued its work.
Upvotes: 1