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>
impl<MakeFutureT, FutureT, BackoffT, T, E, OnRetryT> RetryFuture<MakeFutureT, FutureT, BackoffT, OnRetryT>
sourcepub fn max_delay(self, delay: Duration) -> Self
pub fn max_delay(self, delay: Duration) -> Self
Set the max duration to sleep between each attempt.
sourcepub fn no_backoff(
self,
) -> RetryFuture<MakeFutureT, FutureT, NoBackoff, OnRetryT> ⓘ
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.
sourcepub fn exponential_backoff(
self,
initial_delay: Duration,
) -> RetryFuture<MakeFutureT, FutureT, ExponentialBackoff, OnRetryT> ⓘ
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.
sourcepub fn fixed_backoff(
self,
delay: Duration,
) -> RetryFuture<MakeFutureT, FutureT, FixedBackoff, OnRetryT> ⓘ
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
.
sourcepub fn linear_backoff(
self,
delay: Duration,
) -> RetryFuture<MakeFutureT, FutureT, LinearBackoff, OnRetryT> ⓘ
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.
sourcepub fn custom_backoff<B>(
self,
backoff_strategy: B,
) -> RetryFuture<MakeFutureT, FutureT, B, OnRetryT> ⓘwhere
for<'a> B: BackoffStrategy<'a, E>,
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?;
sourcepub fn on_retry<F, OnRetryFut>(
self,
f: F,
) -> RetryFuture<MakeFutureT, FutureT, BackoffT, F> ⓘ
pub fn on_retry<F, OnRetryFut>( self, f: F, ) -> RetryFuture<MakeFutureT, FutureT, BackoffT, F> ⓘ
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>,
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>,
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>
impl<MakeFutureT, FutureT, BackoffT, OnRetryT> Sync for RetryFuture<MakeFutureT, FutureT, BackoffT, OnRetryT>
impl<MakeFutureT, FutureT, BackoffT, OnRetryT> !UnwindSafe for RetryFuture<MakeFutureT, FutureT, BackoffT, OnRetryT>
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T> FutureExt for T
impl<T> FutureExt for T
source§fn map<U, F>(self, f: F) -> Map<Self, F>
fn map<U, F>(self, f: F) -> Map<Self, F>
source§fn map_into<U>(self) -> MapInto<Self, U>
fn map_into<U>(self) -> MapInto<Self, U>
source§fn then<Fut, F>(self, f: F) -> Then<Self, Fut, F>
fn then<Fut, F>(self, f: F) -> Then<Self, Fut, F>
f
. Read moresource§fn left_future<B>(self) -> Either<Self, B>
fn left_future<B>(self) -> Either<Self, B>
source§fn right_future<A>(self) -> Either<A, Self>
fn right_future<A>(self) -> Either<A, Self>
source§fn into_stream(self) -> IntoStream<Self>where
Self: Sized,
fn into_stream(self) -> IntoStream<Self>where
Self: Sized,
source§fn flatten(self) -> Flatten<Self>
fn flatten(self) -> Flatten<Self>
source§fn flatten_stream(self) -> FlattenStream<Self>
fn flatten_stream(self) -> FlattenStream<Self>
source§fn fuse(self) -> Fuse<Self>where
Self: Sized,
fn fuse(self) -> Fuse<Self>where
Self: Sized,
poll
will never again be called once it has
completed. This method can be used to turn any Future
into a
FusedFuture
. Read moresource§fn inspect<F>(self, f: F) -> Inspect<Self, F>
fn inspect<F>(self, f: F) -> Inspect<Self, F>
source§fn catch_unwind(self) -> CatchUnwind<Self>where
Self: Sized + UnwindSafe,
fn catch_unwind(self) -> CatchUnwind<Self>where
Self: Sized + UnwindSafe,
source§fn remote_handle(self) -> (Remote<Self>, RemoteHandle<Self::Output>)where
Self: Sized,
fn remote_handle(self) -> (Remote<Self>, RemoteHandle<Self::Output>)where
Self: Sized,
()
on completion and sends
its output to another future on a separate task. Read moresource§fn boxed<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + Send + 'a>>
fn boxed<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + Send + 'a>>
source§fn boxed_local<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + 'a>>where
Self: Sized + 'a,
fn boxed_local<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + 'a>>where
Self: Sized + 'a,
source§fn unit_error(self) -> UnitError<Self>where
Self: Sized,
fn unit_error(self) -> UnitError<Self>where
Self: Sized,
Future<Output = T>
into a
TryFuture<Ok = T, Error = ()
>.source§fn never_error(self) -> NeverError<Self>where
Self: Sized,
fn never_error(self) -> NeverError<Self>where
Self: Sized,
Future<Output = T>
into a
TryFuture<Ok = T, Error = Never
>.