#![deny(missing_docs)]
use std::time::Duration;
#[derive(Debug, Clone)]
pub struct RetryPolicy {
pub max_retries: u32,
pub initial_backoff: Duration,
pub max_backoff: Duration,
}
impl Default for RetryPolicy {
fn default() -> Self {
Self {
max_retries: 3,
initial_backoff: Duration::from_millis(500),
max_backoff: Duration::from_secs(10),
}
}
}
impl RetryPolicy {
pub fn backoff_for(&self, attempt: u32) -> Duration {
let backoff = self
.initial_backoff
.saturating_mul(2u32.saturating_pow(attempt));
std::cmp::min(backoff, self.max_backoff)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn backoff_for_handles_overflow() {
let policy = RetryPolicy::default();
assert_eq!(policy.backoff_for(1000), policy.max_backoff);
}
#[test]
fn default_policy_matches_documented_values() {
let policy = RetryPolicy::default();
assert_eq!(policy.max_retries, 3);
assert_eq!(policy.initial_backoff, Duration::from_millis(500));
assert_eq!(policy.max_backoff, Duration::from_secs(10));
}
#[test]
fn backoff_for_capped_at_max() {
let policy = RetryPolicy {
max_retries: 10,
initial_backoff: Duration::from_secs(1),
max_backoff: Duration::from_secs(5),
};
assert_eq!(policy.backoff_for(5), Duration::from_secs(5));
}
}