Polly with .NET 6, Part 5 - Using a Cancellation Token

Download full source code.

Want to learn more about Polly? Check out my Pluralsight course on it.

This is a quick post to show you how to use Polly with .NET 6 to make a web service request that can be canceled if it is taking too long.

With the cancellation token, the current request will be canceled, and any remaining retries will be abandoned.

I am reusing code from earlier posts on Polly and .NET 6, so I not going to explain everything in detail.

The retry policy

I have a simple retry policy that will retry a request up to 3 times.

builder.Services.AddSingleton<IAsyncPolicy<HttpResponseMessage>>(
    Policy.HandleResult<HttpResponseMessage>(
        r => !r.IsSuccessStatusCode).RetryAsync(3));

An endpoint that fails

Here is a simple endpoint that fails 75% of the time, and responds slowly (note the one second delay on line 7).

 1int _requestCount = 0;
 2
 3app.MapGet("/Inventory/{id}", async (int id) =>
 4{
 5    _requestCount++;
 6
 7    await Task.Delay(TimeSpan.FromSeconds(1));
 8    if (_requestCount % 4 == 0) // only one of out four requests will succeed
 9    {
10        System.Console.WriteLine($"{_requestCount} It worked!");
11        return Results.Ok(15);
12    }
13
14    System.Console.WriteLine($"{_requestCount} Something went wrong");
15    return Results.Problem("Something went wrong");
16});

An endpoint that calls the failing endpoint

Here is an endpoint that calls the failing endpoint, and uses the retry policy to retry the request.

It also uses a cancellation token to cancel the request if it takes too long. In this case, the request will be canceled after 3 seconds, any remaining retries will also be abandoned.

The cancellation token is passed to the policy.ExecuteAsync method on lines 15/16.

 1app.MapGet("/Catalog/{id}", async (int id, IAsyncPolicy<HttpResponseMessage> policy) =>
 2{
 3    var cts = new CancellationTokenSource(3000);
 4    var cancellationToken = cts.Token;
 5
 6    HttpClient httpClient = new HttpClient()
 7    {
 8        BaseAddress = new System.Uri(@"http://localhost:5000/")
 9    };
10    string requestEndpoint = $"Inventory/{id}";
11
12    HttpResponseMessage response;
13    try
14    {
15        response = await policy.ExecuteAsync((ct) => 
16            httpClient.GetAsync(requestEndpoint, ct), cancellationToken);
17    }
18    catch (OperationCanceledException oce)
19    {
20        System.Console.WriteLine($"Request timed out, the cancellation token was triggered. {oce.Message}");
21        return Results.Problem($"Request timed out, the cancellation token was triggered. {oce.Message}");
22    }
23
24    if (response.IsSuccessStatusCode)
25    {
26        int itemsInStock = await response.Content.ReadFromJsonAsync<int>();
27        return Results.Ok(itemsInStock);
28    }
29    return Results.Problem("Something went wrong calling the inventory endpoint");
30});
 
That’s all there is to it.

The attached zip file has the full source code.

Download full source code.

comments powered by Disqus

Related