How can I use Polly for retries with a cancellation token?
Asked Answered
T

1

5

I'm new to Polly so there may be a completely different approach compared to the one I'm trying to do and that would be perfectly OK.

My goals are this:

  1. token may be canceled due to timeout or request
  2. Retry forever until either success or token is canceled.
  3. When requesting cancellation waits should be exited immediately

Although the method I have worked it seems like I'm missing something and there's probably a better/cleaner way to accomplish what I want. I'm specifically thinking of this line .WaitAndRetryForever(retryAttempt => TimeSpan.Zero,. I feel like I should be able to pass retryDelay in here instead of TimeSpan.Zero but if I do that when cancellation is requested it doesn't return until the retryDelay has completed waiting rather than immediately like I want.

I did see that the .Execute looks like it can do something with a cancellation token but I couldn't figure out how to use that so if that's my answer please ignore my other ramblings.

Just in case one of the Polly NuGet developers sees this what I expected to see was an overload for WaitAndRetryForever that took a cancellation token as a parameter so that it could return immediately if it were canceled. I hesitate to make that an official suggestion because I'm so new to Polly I'm not sure if that makes sense.

This is the method I'm currently using:

internal static void Retry(Action action, TimeSpan retryDelay, CancellationToken token)
{
    try
    {
        Policy
            .Handle<IOException>()
            .WaitAndRetryForever(retryAttempt => TimeSpan.Zero,
                (ex, delay, context) =>
                {
                    Task.Delay(retryDelay, token).GetAwaiter().GetResult();
                    token.ThrowIfCancellationRequested();
                    //Log exception here
                })
            .Execute(() =>
            {
                token.ThrowIfCancellationRequested();
                action.Invoke();
            });
    }
    catch (OperationCanceledException)
    {
        //Log cancellation here
        throw;
    }
    catch (Exception ex)
    {
        //Log exception here
        throw;
    }
}
Taille answered 4/9, 2019 at 4:15 Comment(0)
S
10

An overload of Execute takes a CancellationToken:

.Execute((ct) =>
{
    ct.ThrowIfCancellationRequested();
    action.Invoke();
}, token);

This token will also be applied to the delay handled within WaitAndRetryForever.

Try it online

Silique answered 4/9, 2019 at 4:25 Comment(1)
I didn't know how to read the IntelliSense. I had tried putting token in the right spot where you put it but I wasn't adding the ct for the local variable. Seems kind obvious now that I see it. ThanksTaille

© 2022 - 2024 — McMap. All rights reserved.