PhoenixMicro.Utils.Backoff (PhoenixMicro v1.0.0)

Copy Markdown View Source

Shared exponential backoff with optional full jitter.

Used by Consumer.RetryScheduler, Transport.RabbitMQ, Transport.Kafka, Transport.NATS, and Transport.RedisStreams for reconnect delays.

Algorithm

Full jitter (default, recommended for distributed systems):

delay = random_between(0, min(cap, base * 2^attempt))

Decorrelated jitter (alternative — avoids thundering herd even better):

delay = random_between(base, min(cap, last_delay * 3))

No jitter (deterministic — useful in tests):

delay = min(cap, base * 2^attempt)

Usage

iex> PhoenixMicro.Utils.Backoff.next_delay(3, base: 500, cap: 30_000)
# returns something between 0 and 4000ms (full jitter)

iex> PhoenixMicro.Utils.Backoff.sequence(5, base: 100, cap: 5_000, jitter: false)
[100, 200, 400, 800, 1600]

Summary

Functions

Returns the next backoff delay in milliseconds for the given attempt number.

Returns a list of count delay values — useful for testing retry sequences.

Sleeps for the calculated backoff delay. Returns the delay used (useful for logging).

Types

opts()

@type opts() :: [
  base: pos_integer(),
  cap: pos_integer(),
  jitter: boolean() | :decorrelated,
  multiplier: number()
]

Functions

next_delay(attempt, opts \\ [])

@spec next_delay(pos_integer(), opts()) :: non_neg_integer()

Returns the next backoff delay in milliseconds for the given attempt number.

attempt is 1-indexed (first retry = 1).

Options

  • :base — base delay in ms (default: 500)
  • :cap — maximum delay in ms (default: 30_000)
  • :jittertrue for full jitter, false for none (default: true)
  • :multiplier — exponential factor (default: 2)

sequence(count, opts \\ [])

@spec sequence(non_neg_integer(), opts()) :: [non_neg_integer()]

Returns a list of count delay values — useful for testing retry sequences.

Example

iex> PhoenixMicro.Utils.Backoff.sequence(4, base: 100, cap: 1_000, jitter: false)
[100, 200, 400, 800]

sleep(attempt, opts \\ [])

@spec sleep(pos_integer(), opts()) :: non_neg_integer()

Sleeps for the calculated backoff delay. Returns the delay used (useful for logging).