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 to randomLow)
  • 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 time
  • iterations — 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 time
  • iterations — 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 time
  • iterations — 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 time
  • 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 to low, 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 to low, 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 task
  • low — 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 to low, 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.