RetryHelper
using System;
using System.Runtime.CompilerServices;
namespace Polly.Retry
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
internal static class RetryHelper
{
private const double JitterFactor = 0.5;
private const double ExponentialFactor = 2;
public static bool IsValidDelay(TimeSpan delay)
{
return delay >= TimeSpan.Zero;
}
public static TimeSpan GetRetryDelay(DelayBackoffType type, bool jitter, int attempt, TimeSpan baseDelay, TimeSpan? maxDelay, ref double state, Func<double> randomizer)
{
try {
TimeSpan retryDelayCore = GetRetryDelayCore(type, jitter, attempt, baseDelay, ref state, randomizer);
if (maxDelay.HasValue) {
TimeSpan valueOrDefault = maxDelay.GetValueOrDefault();
if (retryDelayCore > valueOrDefault)
return maxDelay.Value;
}
return retryDelayCore;
} catch (OverflowException) {
return maxDelay ?? TimeSpan.MaxValue;
}
}
private static TimeSpan GetRetryDelayCore(DelayBackoffType type, bool jitter, int attempt, TimeSpan baseDelay, ref double state, Func<double> randomizer)
{
if (!(baseDelay == TimeSpan.Zero)) {
if (!jitter) {
switch (type) {
case DelayBackoffType.Constant:
return baseDelay;
case DelayBackoffType.Linear:
return TimeSpan.FromMilliseconds((double)(attempt + 1) * baseDelay.TotalMilliseconds);
case DelayBackoffType.Exponential:
return TimeSpan.FromMilliseconds(Math.Pow(2, (double)attempt) * baseDelay.TotalMilliseconds);
default:
throw new ArgumentOutOfRangeException("type", type, "The retry backoff type is not supported.");
}
}
switch (type) {
case DelayBackoffType.Constant:
return ApplyJitter(baseDelay, randomizer);
case DelayBackoffType.Linear:
return ApplyJitter(TimeSpan.FromMilliseconds((double)(attempt + 1) * baseDelay.TotalMilliseconds), randomizer);
case DelayBackoffType.Exponential:
return DecorrelatedJitterBackoffV2(attempt, baseDelay, ref state, randomizer);
default:
throw new ArgumentOutOfRangeException("type", type, "The retry backoff type is not supported.");
}
}
return baseDelay;
}
private static TimeSpan (int attempt, TimeSpan baseDelay, ref double prev, Func<double> randomizer)
{
double val = (double)TimeSpan.MaxValue.Ticks - 1000;
long ticks = baseDelay.Ticks;
double num = (double)attempt + randomizer();
double num2 = Math.Pow(2, num) * Math.Tanh(Math.Sqrt(4 * num));
double num3 = num2 - prev;
prev = num2;
return TimeSpan.FromTicks((long)Math.Min(num3 * 0.7142857142857143 * (double)ticks, val));
}
private static TimeSpan ApplyJitter(TimeSpan delay, Func<double> randomizer)
{
double num = delay.TotalMilliseconds * 0.5 / 2;
double num2 = delay.TotalMilliseconds * 0.5 * randomizer() - num;
return TimeSpan.FromMilliseconds(delay.TotalMilliseconds + num2);
}
}
}