pub(crate) struct Backoff {
attempt: u32,
max_attempts: u32,
base_ms: u64,
max_exponent: u32,
}
impl Backoff {
pub(crate) fn new(max_attempts: u32, base_ms: u64, max_exponent: u32) -> Self {
Self {
attempt: 0,
max_attempts,
base_ms,
max_exponent,
}
}
pub(crate) fn next_delay_ms(&mut self) -> Option<u64> {
self.attempt = self.attempt.saturating_add(1);
if self.attempt > self.max_attempts {
return None;
}
let exponent = self.attempt.min(self.max_exponent);
Some(self.base_ms.saturating_mul(1u64 << exponent))
}
pub async fn sleep_next(&mut self) -> bool {
let Some(delay_ms) = self.next_delay_ms() else {
return false;
};
tokio::time::sleep(std::time::Duration::from_millis(delay_ms)).await;
true
}
pub(crate) fn reset(&mut self) {
self.attempt = 0;
}
}