1use std::time::Duration;
4use tokio::time::sleep;
5
6pub async fn retry_with_backoff<F, Fut, T, E>(
10 label: &str,
11 max_retries: u32,
12 mut operation: F,
13) -> Result<T, E>
14where
15 F: FnMut() -> Fut,
16 Fut: std::future::Future<Output = Result<T, E>>,
17 E: std::fmt::Display,
18{
19 let mut attempt = 0;
20 loop {
21 match operation().await {
22 Ok(val) => return Ok(val),
23 Err(e) => {
24 attempt += 1;
25 if attempt > max_retries {
26 return Err(e);
27 }
28 let delay = Duration::from_secs(1 << (attempt - 1)); eprintln!(
30 " [retry] {} failed (attempt {}/{}): {}. Retrying in {:?}...",
31 label, attempt, max_retries, e, delay
32 );
33 sleep(delay).await;
34 }
35 }
36 }
37}