How to use WaitAndRetry with jitter retry intervals depending on the Exception thrown
See original GitHub issueI would like to apply a WaitAndRetry policy with different parameters, depending on the Exception thrown, for the jitter function calculating the retry intervals. Let’s say that for Type1Exception
I would like to feed to the function a specific couple of maxValue
and seedValue
and for Type2Exception
others. A simple jitter function that calculates the retry intervals is as follows:
IEnumerable<TimeSpan> GetRetryIntervals(int maxRetries, TimeSpan seedDelay, TimeSpan maxDelay)
{
var jitterer = new Random();
int retries = 0;
double seed = seedDelay.TotalMilliseconds;
double max = maxDelay.TotalMilliseconds;
double current = seed;
while (++retries <= maxRetries)
{
if (retries == maxRetries)
{
yield return maxDelay;
yield break;
}
current = Math.Min(max, Math.Max(seed, current * jitterer.NextDouble()));
yield return TimeSpan.FromMilliseconds(current);
}
}
The only way I found to use the jitter with such requirements is to retrieve both jitter intervals before creating the policy and use retryCount
as index:
var type1Intervals = GetRetryIntervals(10, TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(10000));
var type2Intervals = GetRetryIntervals(10, TimeSpan.FromMilliseconds(50), TimeSpan.FromMilliseconds(20000));
Policy
.Handle<Exception>()
.WaitAndRetryAsync(5, async (exception, retryCount) =>
{
if(exception is Type1Exception)
{
await Task.Delay(type1Intervals.ElementAt(retryCount)).ConfigureAwait(false);
}
if(exception is Type2Exception)
{
await Task.Delay(type2Intervals.ElementAt(retryCount)).ConfigureAwait(false);
}
}
})
// execute the command
.ExecuteAsync(async () => await DoSomething())
.ConfigureAwait(false);
This solution indeed works but it is neither elegant not optimized. Is there a more proper way to implement it?
Issue Analytics
- State:
- Created 4 years ago
- Comments:5 (4 by maintainers)
Top Results From Across the Web
Polly.Contrib.WaitAndRetry
Polly.Contrib.WaitAndRetry is an extension library for Polly containing helper methods for a variety of wait-and-retry strategies.
Read more >How to throw final error using WaitAndRetry and Execute?
1 Answer 1 · If the retry limit has not been exceeded then it will perform yet another retry attempt · If the...
Read more >Better Retries with Exponential Backoff and Jitter
We can use the exponential backoff algorithm in Resilience4j retry by configuring its IntervalFunction that accepts an initialInterval and a ...
Read more >Polly 7.2.4
Pow(2, retryAttempt)) ); // Retry a specified number of times, using a function to // calculate the duration to wait between retries based...
Read more >Exploring the Polly.Contrib.WaitAndRetry helpers - Ben Hyrman
In my code, I use Polly in several places to retry remote calls. ... After the last wait and retry, Polly will kick...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
@FrancescoReviso The code in the comment above will apply the “type 1” WaitAndRetry behaviour to any
exception is Type1Exception
, and the other WaitAndRetry behaviour to all other exceptions.Re:
If you want the WaitAndRetry policy to not apply at all for one exception type, you can make a policy to handle all exceptions except that, by using a single handle clause like this:
A couple of technical comments about the original quoted code, in case you eventually settle on a solution more like that.
First, with
.WaitAndRetryAsync(...)
, you don’t need to manually callawait Task.Delay(type1Intervals.ElementAt(retryCount))
yourself. The call toawait Task.Delay(...)
is already built in to the policy implementation. You only need to configure the policy to specify the delay timespans, as shown in the readme examples for WaitAndRetry.Second, be aware that:
with
will get a new enumerator at each call to
.ElementAt(...)
, and thus each call to.ElementAt(retryCount)
in your original code will in fact be based on a different, freshly-realised sequence of the enumerable. With the original code, you might want to add a.ToList()
or.ToArray()
thus:to reify the sequence just once.