use core::sync::atomic::{AtomicBool, Ordering};
use core::time::Duration;
use relentless::{RetryError, RetryExt, predicate, retry, stop, wait};
use std::sync::Arc;
fn main() {
let result = (|| -> Result<&str, &str> { Err("service unavailable") })
.retry()
.stop(stop::attempts(100))
.wait(wait::fixed(Duration::from_millis(100)))
.timeout(Duration::from_millis(250))
.call();
match result {
Ok(val) => println!("pattern 1 — success: {val}"),
Err(RetryError::Exhausted { last }) => {
println!("pattern 1 — deadline exceeded, last: {last:?}");
}
Err(e) => println!("pattern 1 — rejected: {e:?}"),
}
#[derive(Debug, PartialEq)]
enum ServiceError {
Transient(&'static str),
Cancelled,
}
let cancelled = Arc::new(AtomicBool::new(false));
let flag = Arc::clone(&cancelled);
let attempts_before_cancel = Arc::new(std::sync::Mutex::new(0_u32));
let counter = Arc::clone(&attempts_before_cancel);
let result = retry(|_state| -> Result<(), ServiceError> {
if cancelled.load(Ordering::Relaxed) {
return Err(ServiceError::Cancelled);
}
let mut n = counter.lock().unwrap();
*n += 1;
if *n >= 3 {
flag.store(true, Ordering::Relaxed);
}
drop(n);
Err(ServiceError::Transient("connection refused"))
})
.stop(stop::attempts(100))
.wait(wait::fixed(Duration::ZERO)) .when(predicate::error(|e: &ServiceError| {
matches!(e, ServiceError::Transient(_))
}))
.call();
match result {
Ok(val) => println!("pattern 2 — success: {val:?}"),
Err(RetryError::Rejected { last }) => {
println!("pattern 2 — cancelled after flag set, error: {last:?}");
}
Err(RetryError::Exhausted { last }) => {
println!("pattern 2 — exhausted: {last:?}");
}
}
}