Home > Software design >  TaskCanceledException not being caught when using httpclient with polly policy
TaskCanceledException not being caught when using httpclient with polly policy

Time:12-26

I have a .net 6 console app that I configured with polly policies depending on what each service does.

Program.cs

try
{
  //other setup code

  services
   .AddHttpClient<ISubjectData, SubjectData>()
   .AddTransientHttpErrorPolicy(ConfigurePolicy);
   
  //other setup code

    IAsyncPolicy<HttpResponseMessage> ConfigurePolicy(PolicyBuilder<HttpResponseMessage> policy)
    {
        try
        {
            return policy.Or<TaskCanceledException>()
                         .WaitAndRetryAsync(Backoff.DecorrelatedJitterBackoffV2(TimeSpan.FromSeconds(10), 5));
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
            throw;
        }
    }
}
catch(Exception e)
{
  Console.WriteLine(e);
}

The policy is working, however, the program is throwing an unhandled exception which is TaskCanceledException because the HttpClient timed out, which isn't being caught by either catch statements or the policy in ConfigurePolicy.

How can I catch this error, since it is crashing the app?

Also, is there a way to allow Polly to override HTTP client timeout depending on how long it takes to complete all retries?

CodePudding user response:

TL;DR:
You can't catch the exception because you wrapped the policy definition with try- catches.


In case of Polly the policy definition and its execution are separated.

  1. You define a policy (or a combination of policies)
  2. You are decorating some method(s) with the above policy
  3. You are executing the decorated method explicitly or implicitly through the policy.

Whenever you register a typed/named HttpClient and decorate its methods with an IAsyncPolicy<HttpResponseMessage> then you are doing only the first two steps.

Whenever you call a method on the HttpClient, like PostAsync or SendAsync that's where the policy is being executed on your behalf / implicitly (via a special DelegatingHandler).

That's where you can catch the exceptions

  • ones which is thrown either by the HttpClient (like TaskCancelledException, HttpRequestException, etc.)
  • or those that are thrown by one of the policies (like TimeOutRejectedException, BrokenCircuitException, etc.)

UPDATE #1

What is confusing to me, is why does a try-catch block that covers my entire Program.cs not catch the exception, but a try-catch block in the scope of the request does? Aren't exceptions propagated back to the original caller? (The original caller would be a method inside my Program.cs file)

Try catch inside the ConfigurePolicy

As I stated above, here you are building the policy, not executing it. So, the try-catch here can be used to detect and resolve misconfiguration.

Try catch inside Program

Yet again the AddHttpClient and AddTransientHttpErrorPolicy are just builder methods. They are not executing any http request on your behalf. So, wrapping this code into try-catch can help you to spot misconfiguration.

Your try-catch is covering those exceptions which are thrown by the Main but not those which are thrown by different threads which are not in the Main.

  • Related