Quantcast
Channel: Active questions tagged retry-logic - Stack Overflow
Viewing all articles
Browse latest Browse all 950

Handling TaskCanceledException when HttpClient times out

$
0
0

I'm trying to use Microsoft.Extensions.Http.Polly policy handler for retries when TaskCanceledException or http transient errors, but it's not working properly.

I wrote the minimal API below just for testing:

Program.cs

using Polly;using Polly.Extensions.Http;using Polly.Retry;WebApplicationBuilder builder = WebApplication.CreateBuilder(args);AsyncRetryPolicy<HttpResponseMessage>? policy = HttpPolicyExtensions.HandleTransientHttpError()    .Or<TaskCanceledException>()    .WaitAndRetryAsync(5, _ => TimeSpan.FromSeconds(5));builder.Services.AddHttpClient("test", client =>    {        client.BaseAddress = new Uri("http://localhost:5000");        client.Timeout = TimeSpan.FromSeconds(2);    })    .AddPolicyHandler(policy);WebApplication app = builder.Build();app.MapPost("/status/{code}",    async (string code, IHttpClientFactory httpClientFactory, CancellationToken cancellationToken) =>    {        HttpClient client = httpClientFactory.CreateClient("test");        HttpResponseMessage response = await client.GetAsync($"/status/{code}", cancellationToken);        response.EnsureSuccessStatusCode();        return response.Content.ReadAsStringAsync(cancellationToken);    });app.MapPost("/timeout/{timeout:int}",    async (int timeout, IHttpClientFactory httpClientFactory, CancellationToken cancellationToken) =>    {        HttpClient client = httpClientFactory.CreateClient("test");        HttpResponseMessage response = await client.GetAsync($"/timeout/{timeout}", cancellationToken);        response.EnsureSuccessStatusCode();        return response.Content.ReadAsStringAsync(cancellationToken);    });#region Simulated APIapp.MapGet("/status/{code:int}", (int code) => Results.StatusCode(code));app.MapGet("/timeout/{timeout:int}", async (int timeout) =>{    await Task.Delay(TimeSpan.FromSeconds(timeout));    return Results.Ok();});#endregionapp.Run();

After calling POST http://localhost:5000/timeout/10 it raises this exception without any further attempts:

Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]An unhandled exception has occurred while executing the request.System.Threading.Tasks.TaskCanceledException: The request was canceled due to the configured HttpClient.Timeout of 2 seconds elapsing.---> System.TimeoutException: A task was canceled.---> System.Threading.Tasks.TaskCanceledException: A task was canceled. at Polly.Retry.AsyncRetryEngine.ImplementationAsync[TResult](Func`3 action, Context context, CancellationToken cancellationToken, ExceptionPredicates shouldRetryExceptionPredicates, ResultPredicates`1 shouldRetryResultPredicates, Func`5 onRetryAsync, Int32 permittedRetryCount, IEnumerable`1 sleepDurationsEnumerable, Func`4 sleepDurationProvider, Boolean continueOnCapturedContext) at Polly.AsyncPolicy`1.ExecuteAsync(Func`3 action, Context context, CancellationToken cancellationToken, Boolean continueOnCapturedContext)        at Microsoft.Extensions.Http.PolicyHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) at Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler.<>c__DisplayClass5_0.<<SendCoreAsync>g__Core|0>d.MoveNext()--- End of stack trace from previous location --- at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken) --- End of inner exception stack trace --- --- End of inner exception stack trace --- at System.Net.Http.HttpClient.HandleFailure(Exception e, Boolean telemetryStarted, HttpResponseMessage response, CancellationTokenSource cts, CancellationToken cancellationToken, CancellationTokenSource pendingRequestsCts) at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken) at Program.<>c.<<<Main>$>b__0_3>d.MoveNext() in Z:\Repositories\POCs\PollyRetryTest\PollyRetryTest\Program.cs:line 35--- End of stack trace from previous location --- at Microsoft.AspNetCore.Http.RequestDelegateFactory.<ExecuteTaskOfT>g__ExecuteAwaited|129_0[T](Task`1 task, HttpContext httpContext, JsonTypeInfo`1 jsonTypeInfo) at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)     

What am I doing wrong? Do I have to override the primary handler?


Viewing all articles
Browse latest Browse all 950

Trending Articles