RetryFuture

Struct RetryFuture 

Source
pub struct RetryFuture<MakeFutureT, FutureT, BackoffT, OnRetryT> { /* private fields */ }
Expand description

A retryable future.

Can be created by calling retry_fn.

Implementations§

Source§

impl<MakeFutureT, FutureT, BackoffT, T, E, OnRetryT> RetryFuture<MakeFutureT, FutureT, BackoffT, OnRetryT>
where MakeFutureT: FnMut() -> FutureT, FutureT: Future<Output = Result<T, E>>,

Source

pub fn max_delay(self, delay: Duration) -> Self

Set the max duration to sleep between each attempt.

Source

pub fn no_backoff( self, ) -> RetryFuture<MakeFutureT, FutureT, NoBackoff, OnRetryT>

Remove the backoff strategy.

This will make the future be retried immediately without any delay in between attempts.

Source

pub fn exponential_backoff( self, initial_delay: Duration, ) -> RetryFuture<MakeFutureT, FutureT, ExponentialBackoff, OnRetryT>

Use exponential backoff for retrying the future.

The first delay will be initial_delay and afterwards the delay will double every time.

Source

pub fn fixed_backoff( self, delay: Duration, ) -> RetryFuture<MakeFutureT, FutureT, FixedBackoff, OnRetryT>

Use a fixed backoff for retrying the future.

The delay between attempts will always be delay.

Source

pub fn linear_backoff( self, delay: Duration, ) -> RetryFuture<MakeFutureT, FutureT, LinearBackoff, OnRetryT>

Use a linear backoff for retrying the future.

The delay will be delay * attempt so it’ll scale linear with the attempt.

Source

pub fn custom_backoff<B>( self, backoff_strategy: B, ) -> RetryFuture<MakeFutureT, FutureT, B, OnRetryT>
where for<'a> B: BackoffStrategy<'a, E>,

Use a custom backoff specified by some function.

use std::time::Duration;

tryhard::retry_fn(|| read_file("Cargo.toml"))
    .retries(10)
    .custom_backoff(|attempt, _error: &std::io::Error| {
        if attempt < 5 {
            Duration::from_millis(100)
        } else {
            Duration::from_millis(500)
        }
    })
    .await?;

You can also stop retrying early:

use std::time::Duration;
use tryhard::RetryPolicy;

tryhard::retry_fn(|| read_file("Cargo.toml"))
    .retries(10)
    .custom_backoff(|attempt, error: &std::io::Error| {
        if error.to_string().contains("foobar") {
            // returning this will cancel the loop and
            // return the most recent error
            RetryPolicy::Break
        } else {
            RetryPolicy::Delay(Duration::from_millis(50))
        }
    })
    .await?;
Source

pub fn on_retry<F, OnRetryFut>( self, f: F, ) -> RetryFuture<MakeFutureT, FutureT, BackoffT, F>
where F: Fn(u32, Option<Duration>, &E) -> OnRetryFut,

Some async computation that will be spawned before each retry.

This can for example be used for telemtry such as logging or other kinds of tracking.

The future returned will be given to tokio::spawn so wont impact the actual retrying.

§Example

For example to print and gather all the errors you can do:

use std::sync::Arc;
use tokio::sync::Mutex;

let all_errors = Arc::new(Mutex::new(Vec::new()));

tryhard::retry_fn(|| async {
    // just some dummy computation that always fails
    Err::<(), _>("fail")
})
    .retries(10)
    .on_retry(|_attempt, _next_delay, error: &&'static str| {
        // the future must be `'static` so it cannot contain references
        let all_errors = Arc::clone(&all_errors);
        let error = error.clone();
        async move {
            eprintln!("Something failed: {}", error);
            all_errors.lock().await.push(error);
        }
    })
    .await
    .unwrap_err();

assert_eq!(all_errors.lock().await.len(), 10);

Trait Implementations§

Source§

impl<F, Fut, B, T, E, OnRetryT> Future for RetryFuture<F, Fut, B, OnRetryT>
where F: FnMut() -> Fut, Fut: Future<Output = Result<T, E>>, for<'a> B: BackoffStrategy<'a, E>, for<'a> <B as BackoffStrategy<'a, E>>::Output: Into<RetryPolicy>, OnRetryT: OnRetry<E>,

Source§

type Output = Result<T, E>

The type of value produced on completion.
Source§

fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering the current task for wakeup if the value is not yet available. Read more
Source§

impl<'__pin, MakeFutureT, FutureT, BackoffT, OnRetryT> Unpin for RetryFuture<MakeFutureT, FutureT, BackoffT, OnRetryT>
where PinnedFieldsOf<__Origin<'__pin, MakeFutureT, FutureT, BackoffT, OnRetryT>>: Unpin,

Auto Trait Implementations§

§

impl<MakeFutureT, FutureT, BackoffT, OnRetryT> !Freeze for RetryFuture<MakeFutureT, FutureT, BackoffT, OnRetryT>

§

impl<MakeFutureT, FutureT, BackoffT, OnRetryT> !RefUnwindSafe for RetryFuture<MakeFutureT, FutureT, BackoffT, OnRetryT>

§

impl<MakeFutureT, FutureT, BackoffT, OnRetryT> Send for RetryFuture<MakeFutureT, FutureT, BackoffT, OnRetryT>
where MakeFutureT: Send, FutureT: Send, BackoffT: Send, OnRetryT: Send,

§

impl<MakeFutureT, FutureT, BackoffT, OnRetryT> Sync for RetryFuture<MakeFutureT, FutureT, BackoffT, OnRetryT>
where MakeFutureT: Sync, FutureT: Sync, BackoffT: Sync, OnRetryT: Sync,

§

impl<MakeFutureT, FutureT, BackoffT, OnRetryT> !UnwindSafe for RetryFuture<MakeFutureT, FutureT, BackoffT, OnRetryT>

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> 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<F> IntoFuture for F
where F: Future,

Source§

type Output = <F as Future>::Output

The output that the future will produce on completion.
Source§

type IntoFuture = F

Which kind of future are we turning this into?
Source§

fn into_future(self) -> <F as IntoFuture>::IntoFuture

Creates a future from a value. 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.