Skip to main content

Backoff

Struct Backoff 

Source
pub struct Backoff { /* private fields */ }
Expand description

Re-exported from reliakit-backoff so the backoff schedule is reachable without a separate dependency line. A retry backoff policy.

Backoff is a small, Copy value. Construct one with Backoff::constant, Backoff::linear, or Backoff::exponential, then optionally cap it with Backoff::with_max_delay and Backoff::with_max_retries.

Backoff::delay takes a zero-based attempt number (attempt 0 is the wait before the first retry) and returns the delay, or None when the retry limit has been reached.

Implementations§

Source§

impl Backoff

Source

pub const fn constant(base: Duration) -> Backoff

A constant backoff that always waits base.

Examples found in repository?
examples/async_retry.rs (line 30)
29fn main() {
30    let policy = RetryPolicy::new(4, Backoff::constant(Duration::from_millis(20)))
31        .expect("max_attempts is non-zero");
32
33    let mut attempt = 0;
34    let result: Result<u32, RetryError<&str>> = block_on(retry_async(
35        &policy,
36        || {
37            attempt += 1;
38            let outcome = if attempt < 3 {
39                Err("temporary")
40            } else {
41                Ok(200)
42            };
43            async move { outcome }
44        },
45        |_error| true,
46        |delay| async move {
47            // Your runtime's async sleep goes here. This example resolves
48            // immediately; the sleep future is entirely user-provided.
49            let _ = delay;
50        },
51    ));
52
53    println!("async result after {attempt} attempt(s): {result:?}");
54}
Source

pub const fn linear(base: Duration, step: Duration) -> Backoff

A linear backoff: attempt n waits base + step * n.

Source

pub const fn exponential(base: Duration, factor: u32) -> Backoff

An exponential backoff: attempt n waits base * factor^n.

factor is the integer multiplier (e.g. 2 doubles each attempt). A factor below 2 makes the policy behave like Backoff::constant.

Examples found in repository?
examples/basic_retry.rs (line 20)
17fn main() {
18    let policy = RetryPolicy::new(
19        5,
20        Backoff::exponential(Duration::from_millis(50), 2).with_max_delay(Duration::from_secs(1)),
21    )
22    .expect("max_attempts is non-zero");
23
24    // An operation that fails twice with a temporary error, then succeeds.
25    let mut attempt = 0;
26    let result: Result<&str, RetryError<ApiError>> = retry_with_sleep(
27        &policy,
28        || {
29            attempt += 1;
30            println!("attempt {attempt}");
31            if attempt < 3 {
32                Err(ApiError::Temporary)
33            } else {
34                Ok("payload")
35            }
36        },
37        |error| matches!(error, ApiError::Temporary), // retry only temporary errors
38        |delay| {
39            // You provide the waiting. In real code, call your platform or
40            // runtime sleep here; this example only reports the delay so it
41            // stays dependency-free and instant.
42            println!("  would wait {delay:?} before the next attempt");
43        },
44    );
45    match result {
46        Ok(body) => println!("succeeded with: {body}"),
47        Err(error) => println!("gave up: {error:?}"),
48    }
49
50    // A fatal error stops immediately, even though attempts remain.
51    let mut attempt = 0;
52    let result: Result<&str, RetryError<ApiError>> = retry_with_sleep(
53        &policy,
54        || {
55            attempt += 1;
56            Err(ApiError::Fatal)
57        },
58        |error| matches!(error, ApiError::Temporary),
59        |_delay| {},
60    );
61    println!(
62        "fatal path: stopped after {} attempt(s)",
63        result.unwrap_err().attempts()
64    );
65}
Source

pub const fn with_max_delay(self, max_delay: Duration) -> Backoff

Caps every computed delay at max_delay.

Examples found in repository?
examples/basic_retry.rs (line 20)
17fn main() {
18    let policy = RetryPolicy::new(
19        5,
20        Backoff::exponential(Duration::from_millis(50), 2).with_max_delay(Duration::from_secs(1)),
21    )
22    .expect("max_attempts is non-zero");
23
24    // An operation that fails twice with a temporary error, then succeeds.
25    let mut attempt = 0;
26    let result: Result<&str, RetryError<ApiError>> = retry_with_sleep(
27        &policy,
28        || {
29            attempt += 1;
30            println!("attempt {attempt}");
31            if attempt < 3 {
32                Err(ApiError::Temporary)
33            } else {
34                Ok("payload")
35            }
36        },
37        |error| matches!(error, ApiError::Temporary), // retry only temporary errors
38        |delay| {
39            // You provide the waiting. In real code, call your platform or
40            // runtime sleep here; this example only reports the delay so it
41            // stays dependency-free and instant.
42            println!("  would wait {delay:?} before the next attempt");
43        },
44    );
45    match result {
46        Ok(body) => println!("succeeded with: {body}"),
47        Err(error) => println!("gave up: {error:?}"),
48    }
49
50    // A fatal error stops immediately, even though attempts remain.
51    let mut attempt = 0;
52    let result: Result<&str, RetryError<ApiError>> = retry_with_sleep(
53        &policy,
54        || {
55            attempt += 1;
56            Err(ApiError::Fatal)
57        },
58        |error| matches!(error, ApiError::Temporary),
59        |_delay| {},
60    );
61    println!(
62        "fatal path: stopped after {} attempt(s)",
63        result.unwrap_err().attempts()
64    );
65}
Source

pub const fn with_max_retries(self, max_retries: u32) -> Backoff

Limits the policy to at most max_retries retries.

After this, delay returns None for attempt numbers >= max_retries.

Source

pub const fn base(&self) -> Duration

Returns the base delay.

Source

pub const fn max_delay(&self) -> Duration

Returns the maximum delay cap.

Source

pub const fn max_retries(&self) -> Option<u32>

Returns the retry limit, if any.

Source

pub fn delay(&self, attempt: u32) -> Option<Duration>

Returns the delay to wait before retry attempt (zero-based), or None if the retry limit has been reached.

The result is always clamped to max_delay. All arithmetic saturates and the computation runs in bounded time, so large attempt numbers never overflow, panic, or hang.

Source

pub const fn delays(&self) -> Delays

Returns an iterator over the delays for attempts 0, 1, 2, ....

The iterator ends when the retry limit is reached. With no retry limit it is infinite.

Trait Implementations§

Source§

impl Clone for Backoff

Source§

fn clone(&self) -> Backoff

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for Backoff

Source§

impl Debug for Backoff

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Eq for Backoff

Source§

impl Hash for Backoff

Source§

fn hash<__H>(&self, state: &mut __H)
where __H: Hasher,

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for Backoff

Source§

fn eq(&self, other: &Backoff) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl StructuralPartialEq for Backoff

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.