pub struct Backoff { /* private fields */ }Expand description
When to try again: exponential backoff with a cap, an optional attempt limit and optional deterministic jitter.
The delay after failed attempt n (from 1) is
initial × factorⁿ⁻¹, capped at max, then reduced by up to jitter of
itself (so jitter(0.5, seed) gives between half and all of it).
use std::time::Duration;
use rich_ext::countdown::Backoff;
let secs = Duration::from_secs;
let backoff = Backoff::new(secs(1)).factor(3.0).max(secs(20));
assert_eq!(backoff.delay(1), Some(secs(1)));
assert_eq!(backoff.delay(3), Some(secs(9)));
assert_eq!(backoff.delay(4), Some(secs(20)));
let jittered = backoff.clone().jitter(0.5, 42);
let d = jittered.delay(3).unwrap();
assert!(d >= secs(9) / 2 && d <= secs(9));
assert_eq!(jittered.delay(3), Some(d)); // same seed, same delaysImplementations§
Source§impl Backoff
impl Backoff
Sourcepub fn new(initial: Duration) -> Self
pub fn new(initial: Duration) -> Self
Start at initial, doubling, capped at one minute, attempts unlimited,
no jitter.
Sourcepub fn factor(self, factor: f64) -> Self
pub fn factor(self, factor: f64) -> Self
Multiply the delay by factor after each failure (at least 1).
Sourcepub fn attempts(self, attempts: u32) -> Self
pub fn attempts(self, attempts: u32) -> Self
Give up after attempts attempts in all (at least 1).
Sourcepub fn jitter(self, fraction: f64, seed: u64) -> Self
pub fn jitter(self, fraction: f64, seed: u64) -> Self
Shorten each delay by a pseudo-random part of up to fraction
(0..=1) of it, drawn from seed: the same seed always gives the same
delays, so tests stay deterministic. Seed from the clock or process id
in production so clients spread out.
Sourcepub fn max_attempts(&self) -> Option<u32>
pub fn max_attempts(&self) -> Option<u32>
The attempt limit, if any.
Sourcepub fn delay(&self, attempt: u32) -> Option<Duration>
pub fn delay(&self, attempt: u32) -> Option<Duration>
How long to wait after failed attempt attempt (from 1), or None
when that was the last attempt allowed.