use std::time::Duration;
#[derive(Debug, Clone)]
pub struct RetryPolicy {
pub max_retries: Option<u32>,
pub initial_delay: Duration,
pub max_delay: Duration,
pub backoff_multiplier: f64,
pub jitter: bool,
}
impl Default for RetryPolicy {
fn default() -> Self {
Self {
max_retries: Some(5),
initial_delay: Duration::from_millis(100),
max_delay: Duration::from_secs(30),
backoff_multiplier: 2.0,
jitter: true,
}
}
}
impl RetryPolicy {
pub fn new() -> Self {
Self::default()
}
pub fn with_max_retries(mut self, max_retries: u32) -> Self {
self.max_retries = Some(max_retries);
self
}
pub fn with_infinite_retries(mut self) -> Self {
self.max_retries = None;
self
}
pub fn with_initial_delay(mut self, delay: Duration) -> Self {
self.initial_delay = delay;
self
}
pub fn with_max_delay(mut self, delay: Duration) -> Self {
self.max_delay = delay;
self
}
pub fn with_backoff_multiplier(mut self, multiplier: f64) -> Self {
self.backoff_multiplier = multiplier;
self
}
pub fn with_jitter(mut self, jitter: bool) -> Self {
self.jitter = jitter;
self
}
pub fn delay_for_attempt(&self, attempt: u32) -> Duration {
let base_delay =
self.initial_delay.as_millis() as f64 * self.backoff_multiplier.powi(attempt as i32);
let delay_ms = base_delay.min(self.max_delay.as_millis() as f64) as u64;
Duration::from_millis(delay_ms)
}
pub fn should_retry(&self, attempt: u32) -> bool {
match self.max_retries {
None => true, Some(max) => attempt < max,
}
}
pub fn no_retry() -> Self {
Self {
max_retries: Some(0),
..Default::default()
}
}
pub fn infinite() -> Self {
Self {
max_retries: None,
..Default::default()
}
}
pub fn fixed_delay(delay: Duration, max_retries: u32) -> Self {
Self {
max_retries: Some(max_retries),
initial_delay: delay,
max_delay: delay,
backoff_multiplier: 1.0,
jitter: false,
}
}
}