use core::time::Duration;
use relentless::test_util::VirtualClock;
use relentless::{RetryError, Wait, retry, stop, wait};
const INITIAL_BACKOFF: Duration = Duration::from_millis(100);
const BACKOFF_CAP: Duration = Duration::from_secs(5);
const BUDGET: Duration = Duration::from_millis(400);
fn fetch_with_retries<S, C>(
mut operation: impl FnMut() -> Result<u32, &'static str>,
sleep: S,
clock: C,
) -> Result<u32, RetryError<u32, &'static str>>
where
S: FnMut(Duration),
C: Fn() -> Duration + 'static,
{
retry(move |_| operation())
.wait(wait::exponential(INITIAL_BACKOFF).cap(BACKOFF_CAP))
.stop(stop::never())
.elapsed_clock_fn(clock)
.timeout(BUDGET)
.sleep(sleep)
.call()
}
fn main() {
let always_failing = || Err::<u32, _>("service unavailable");
let clock = VirtualClock::new();
let result = fetch_with_retries(always_failing, clock.sync_sleep(), clock.clock());
assert!(matches!(result, Err(RetryError::Exhausted { .. })));
assert_eq!(
clock.sleeps(),
vec![
Duration::from_millis(100),
Duration::from_millis(200),
Duration::from_millis(100),
],
);
assert_eq!(clock.now(), BUDGET);
println!("retry gave up after backoff schedule {:?}", clock.sleeps());
println!("virtual time elapsed: {:?} (real time: ~0ms)", clock.now());
}