user1094183
user1094183

Reputation: 175

Restsharp polly retry policy based on status

I am trying to manipulate polly retry policy based on response status code. If status code is 500, I need to retry after 3 minutes else I need to retry after 2, 4 seconds. I have something like this right now,

.OrResult<RestResponse>(
    (response) => {
        return !response.IsSuccessful || response.StatusCode != System.Net.HttpStatusCode.Conflict;
    })
.WaitAndRetryAsync(new[] { TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(15) })  

I can possibly add TimeSpan.FromSeconds(180) but I only want to do it if the response status code is 500.

Is there a way to do that?

Upvotes: 1

Views: 4347

Answers (1)

Peter Csala
Peter Csala

Reputation: 22849

The WaitAndRetryAsync has several overloads. In your case you have used one which accepts an IEnumerable<TimeSpan> which defines the retry count and the delays between each attempt.

There are overloads which allows you to define the sleepDurations dynamically. In those cases you have to provide a sleepDurationProvider.

In the bellow example I've used this overload:

 public static AsyncRetryPolicy<TResult> WaitAndRetryAsync<TResult>(
       this PolicyBuilder<TResult> policyBuilder, 
       int retryCount,
       Func<int, DelegateResult<TResult>, Context, TimeSpan> sleepDurationProvider, 
       Func<DelegateResult<TResult>, TimeSpan, int, Context, Task> onRetryAsync)
  • int retryCount: At most how many retry attempts should be issued
  • Func<int, DelegateResult<TResult>, Context, TimeSpan> sleepDurationProvider: A user-defined function which receives the number of retry attempt, the result of the attempt, a context and anticipates a TimeSpan in return
  • Func<DelegateResult<TResult>, TimeSpan, int, Context, Task> onRetryAsync: A user-defined function which is called if the policy should be triggered but before the sleep

With this you can achieve the desired behaviour:

.WaitAndRetryAsync(retryCount: 3, 
    sleepDurationProvider: (int retryCount, DelegateResult<RestResponse> response, Context ctx) =>
{
    if (response.Result.StatusCode == HttpStatusCode.InternalServerError)
        return TimeSpan.FromMinutes(3);
    return retryCount switch
    {
        1 => TimeSpan.FromSeconds(2),
        2 => TimeSpan.FromSeconds(5),
        3 => TimeSpan.FromSeconds(15),
        _ => TimeSpan.FromSeconds(1) //It won't be used due to the retryCount
    };
}, onRetryAsync: (_, __, ___, ____) => Task.CompletedTask);
  • If the response's status code is 500 then return with a 3 minutes sleep duration
    • For every other cases decide the sleep duration based on the number of attempt
  • The onRetryAsync delegate needs to be defined otherwise the compiler will not find this overload

Upvotes: 1

Related Questions