Expand description
A small crate providing an async retry policy with exponential backoff and jitter.
Example: programmatic and macro usage (predicate-aware)
use asyn_retry_policy::RetryPolicy;
use std::time::Duration;
use std::sync::{Arc, atomic::{AtomicU8, Ordering}};
// Programmatic usage with a predicate that inspects the error type (`String` here)
#[tokio::main]
async fn main() {
// predicate gets an `&E`, so when `E = String` it's `&String`.
fn is_retryable(e: &String) -> bool { e == "temporary" }
let mut policy = RetryPolicy::default();
policy.attempts = 5;
policy.jitter = false;
let tries = Arc::new(AtomicU8::new(0));
let res = policy.retry(
{
let tries = tries.clone();
move || {
let tries = tries.clone();
async move {
let prev = tries.fetch_add(1, Ordering::SeqCst);
if prev < 2 { Err::<u8, _>(String::from("temporary")) } else { Ok(0u8) }
}
}
},
is_retryable,
).await;
assert!(res.is_ok());
}Macro usage examples (predicate path and inline closure):
use asyn_retry_policy::retry;
use std::sync::{Arc, atomic::{AtomicU8, Ordering}};
fn should_retry(e: &String) -> bool { e == "tmp" }
#[retry(attempts = 3, predicate = should_retry)]
async fn my_endpoint(tries: Arc<AtomicU8>) -> Result<u8, String> {
let prev = tries.fetch_add(1, Ordering::SeqCst);
if prev < 2 { Err(String::from("tmp")) } else { Ok(7u8) }
}Inline closure predicate example:
use asyn_retry_policy::retry;
use std::sync::{Arc, atomic::{AtomicU8, Ordering}};
#[retry(predicate = |e: &String| e == "tmp")]
async fn my_endpoint_closure(tries: Arc<AtomicU8>) -> Result<u8, String> {
let prev = tries.fetch_add(1, Ordering::SeqCst);
if prev < 2 { Err(String::from("tmp")) } else { Ok(8u8) }
}Structs§
- Retry
Policy - Retry policy configuration