LemonCore. Retry
(lemon_core v0.1.0)
View Source
Shared retry backoff utilities extracted from duplicated implementations across lemon_channels and lemon_gateway.
Summary
Functions
Exponential backoff capped at a maximum value, with optional jitter.
Exponential backoff: base_ms * 2^attempt.
Exponential backoff with a configurable multiplier (factor).
Parses a retry-after value from an HTTP response body.
Adds symmetric jitter to a delay value.
Functions
@spec capped_backoff(pos_integer(), non_neg_integer(), pos_integer(), keyword()) :: pos_integer()
Exponential backoff capped at a maximum value, with optional jitter.
Options
:factor- growth factor (default: 2):jitter- jitter fraction, 0 to disable (default: 0)
Examples
iex> LemonCore.Retry.capped_backoff(500, 2, 10_000)
2000
iex> LemonCore.Retry.capped_backoff(500, 10, 10_000)
10_000
@spec exponential_backoff(pos_integer(), non_neg_integer()) :: pos_integer()
Exponential backoff: base_ms * 2^attempt.
Examples
iex> LemonCore.Retry.exponential_backoff(500, 0)
500
iex> LemonCore.Retry.exponential_backoff(500, 3)
4000
@spec exponential_backoff(pos_integer(), non_neg_integer(), number()) :: pos_integer()
Exponential backoff with a configurable multiplier (factor).
Useful when the growth factor is not 2 (e.g. WhatsApp reconnect uses 1.8).
Examples
iex> LemonCore.Retry.exponential_backoff(2000, 0, 1.8)
2000
@spec parse_retry_after(term()) :: non_neg_integer()
Parses a retry-after value from an HTTP response body.
Supports:
- JSON body with
parameters.retry_after(Telegram-style) - Plain text with "retry after N" pattern
Returns milliseconds, or 0 if not found.
@spec with_jitter(number(), float()) :: non_neg_integer()
Adds symmetric jitter to a delay value.
Returns a value in the range [delay * (1 - jitter_fraction), delay * (1 + jitter_fraction)].
Examples
iex> result = LemonCore.Retry.with_jitter(1000, 0.25)
iex> result >= 750 and result <= 1250
true