ExponentialRandomizedBackoff
Namespace: SnowBank.Threading · class
Provides a state machine that can be used to retry operations after a randomized delay with built-in exponential backoff
Constructors
ExponentialRandomizedBackoff
ExponentialRandomizedBackoff(TimeSpan initial, TimeSpan maximum, double backoffFactor = 2, double randomLow = 1, double randomHigh = 1.5, Random rng = null)
Create a new state machine
initial— Initial delay (after the first failure)maximum— Maximum retry delay (before taking into account the randomization)backoffFactor— Factor that is multiplied with the last delay to get th next delay (must be greater than 0, and usually greater than 1)randomLow— Minimum randomized factor applied to each delay (must be greater than 0)randomHigh— Maximum randomized factor applied to each delay (must be greater than, or equal torandomLow)rng— Pseudo-random number generator used by this instance
Properties
BackoffFactor
double BackoffFactor { get; }
Multiply the delay by this factor after every retry
Initial
TimeSpan Initial { get; }
Initial delay
Iterations
int Iterations { get; }
Number of attempts
Last
TimeSpan Last { get; }
Last delay
Maximum
TimeSpan Maximum { get; }
Maximum delay
RandomHigh
double RandomHigh { get; }
Randomize the delay between RandomLow and this value on every attempt
If equals then there is no randomization
RandomLow
double RandomLow { get; }
Randomize the delay between this value, and RandomHigh on every attempt
If equals then there is no randomization
Time
TimeProvider Time { get; set; }
Provider used to schedule the delays of Wait (the real system clock by default)
A test can inject a fake advanceable provider so that reconnect/retry loops run in virtual time.
Methods
AdvanceBy
Instant AdvanceBy(Instant now)
Computes the earliest instant when the next operation should be attempted again
now— Current time
Returns: Instant in the future with a randomized delay
DateTimeOffset AdvanceBy(DateTimeOffset now)
Computes the earliest instant when the next operation should be attempted again
now— Current time
Returns: Instant in the future with a randomized delay
DateTimeOffset AdvanceBy(DateTime now)
Computes the earliest instant when the next operation should be attempted again
now— Current time
Returns: Instant in the future with a randomized delay
Instant AdvanceBy(Instant now, out int iterations)
Computes the earliest instant when the next operation should be attempted again
now— Current timeiterations— Number of calls to this method since the last Reset
Returns: Instant in the future with a randomized delay
DateTimeOffset AdvanceBy(DateTimeOffset now, out int iterations)
Computes the earliest instant when the next operation should be attempted again
now— Current timeiterations— Number of calls to this method since the last Reset
Returns: Instant in the future with a randomized delay
DateTimeOffset AdvanceBy(DateTime now, out int iterations)
Computes the earliest instant when the next operation should be attempted again
now— Current timeiterations— Number of calls to this method since the last Reset
Returns: Instant in the future with a randomized delay
static Instant AdvanceBy(Instant now, TimeSpan baseDelay, double low = 1, double high = 1.5, Random rng = null)
Computes the next instant after a randomized delay
now— Current timebaseDelay— Base delay (before randomization)low— Minimum randomized factor applied to the base delay (must be greater than 0, defaults to 1)high— Maximum randomized factor applied to the base delay (must be greater or equal tolow, defaults to 1.5)rng— Pseudo-random number generator used to compute the delay
Returns: Instant in the future that is after now by a randomized delay 'd' that is equal to the baseDelay, multiplied by a random factor between low and high
GetNext
TimeSpan GetNext()
Computes the minimum delay before attempting the next operation
Returns: Randomized delay
TimeSpan GetNext(out int iterations)
Computes the minimum delay before attempting the next operation
iterations— Number of calls to this method since the last Reset
Returns: Randomized delay
static TimeSpan GetNext(TimeSpan baseDelay, double low = 1, double high = 1.5, Random rng = null)
Computes a randomized delay
baseDelay— Base delay (before randomization)low— Minimum randomized factor applied to the base delay (must be greater than 0, defaults to 1)high— Maximum randomized factor applied to the base delay (must be greater or equal tolow, defaults to 1.5)rng— Pseudo-random number generator used to compute the delay
Returns: Randomized delay 'd' that is equal to the base delay, multiplied by a random factor between low and high
await Task.Delay(ExponentialRandomizedBackoff.GetNext(TimeSpan.FromSecondes(30), 0.75, 1.25), ct);
Reset
void Reset()
Reset the delay to the initial value, following a successful operation.
This method should either be called at the start of a new request, or after a successful request, to reset the current state.
This should not be called between unsuccessful attempts, otherwise the delay will never grow by the specified BackoffFactor.
Wait
Task<TimeSpan> Wait(CancellationToken ct)
Returns a task that will complete when the next operation should be attempted
ct— Cancellation token used to abort the task
Returns: Task that will complete when the next delay has elapsed. The result will be the elapsed time.
This is equivalent to calling Task.Delay(backoff.GetNext(), ct), except that it returns the delay itself.
static Task<TimeSpan> Wait(TimeSpan baseDelay, CancellationToken ct, double low = 1, double high = 1.5, Random rng = null)
Returns a task that will complete when the next operation should be attempted, given the specified parameters
baseDelay— Base delay (before randomization)ct— Cancellation token used to abort the tasklow— Minimum randomized factor applied to the base delay (must be greater than 0, defaults to 1)high— Maximum randomzed factor applied to the base delay (must be greater or eqaul tolow, defaults to 1.5)rng— Pseudo-random number generator used to compute the delay
Returns: Task that will complete when the randomized delay has elapsed. The result will be the elapsed time.
This is equivalent to calling Task.Delay(ExponentialRandomizedBackoff.GetNext(baseDelay, low, high, rnd), ct), except that it returns the delay itself.