5 releases
0.2.3 | Mar 14, 2023 |
---|---|
0.2.2 | Aug 5, 2022 |
0.2.1 | Jul 8, 2022 |
0.2.0 | Jul 8, 2022 |
0.1.0 | Jun 7, 2022 |
#1285 in Network programming
2,502 downloads per month
30KB
361 lines
futures-retry-policies
A crate to help retry futures.
use futures_retry_policies::{retry, RetryPolicy};
use std::{ops::ControlFlow, time::Duration};
// 1. Create your retry policy
/// Retries a request n times
pub struct Retries(usize);
// 2. Define how your policy behaves
impl RetryPolicy<Result<(), &'static str>> for Retries {
fn should_retry(&mut self, result: Result<(), &'static str>) -> ControlFlow<Result<(), &'static str>, Duration> {
if self.0 > 0 && result.is_err() {
self.0 -= 1;
// continue to retry on error
ControlFlow::Continue(Duration::from_millis(100))
} else {
// We've got a success, or we've exhauted our retries, so break
ControlFlow::Break(result)
}
}
}
async fn make_request() -> Result<(), &'static str> {
// make a request
# static COUNT: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
# if COUNT.fetch_add(1, std::sync::atomic::Ordering::SeqCst) < 2 { Err("fail") } else { Ok(()) }
}
#[tokio::main]
async fn main() -> Result<(), &'static str> {
// 3. Await the retry with your policy, a sleep function, and your async function.
retry(Retries(3), tokio::time::sleep, make_request).await
}
Tracing
Add the tracing
feature and you can use the Traced
RetryPolicy to automatically
log your retries
Tokio
Add the tokio
feature and you can use the convenience tokio retry methods to skip specifying
[tokio::time::sleep
].
You can also use the [tokio::RetryFutureExt
] trait to support calling retry
directly
on async functions.
#[tokio::main]
async fn main() -> Result<(), &'static str> {
make_request.retry(Retries(3)).await
}
retry-policies
This crate has first class support for the retry-policies crate
use futures_retry_policies::{retry, retry_policies::{ShouldRetry, RetryPolicies}};
use retry_policies::policies::ExponentialBackoff;
enum Error { Retry, DoNotRetry }
impl ShouldRetry for Error {
fn should_retry(&self, _: u32) -> bool { matches!(self, Error::Retry) }
}
async fn make_request() -> Result<(), Error> {
// make a request
# static COUNT: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
# if COUNT.fetch_add(1, std::sync::atomic::Ordering::SeqCst) < 2 { Err(Error::Retry) } else { Ok(()) }
}
#[tokio::main]
async fn main() -> Result<(), Error> {
let backoff = ExponentialBackoff::builder().build_with_max_retries(3);
let policy = RetryPolicies::new(backoff);
retry(policy, tokio::time::sleep, make_request).await
}
Dependencies
~4–34MB
~550K SLoC