use crate::BackoffConfig;
use std::time::Duration;
#[derive(Debug, Clone, PartialEq)]
pub struct SupervisionConfig {
pub max_attempts: Option<u32>,
pub initial_delay: Duration,
pub backoff_multiplier: f64,
pub max_delay: Duration,
}
impl SupervisionConfig {
pub fn next_delay(&self, attempt: u32) -> Duration {
if attempt == 0 {
return self.initial_delay;
}
let backoff = BackoffConfig {
initial_delay: self.initial_delay,
multiplier: self.backoff_multiplier,
max_delay: self.max_delay,
};
backoff.delay_for_attempt(attempt - 1)
}
}
impl Default for SupervisionConfig {
fn default() -> Self {
Self {
max_attempts: Some(5),
initial_delay: Duration::from_secs(1),
backoff_multiplier: 2.0,
max_delay: Duration::from_secs(60),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::time::Duration;
#[test]
fn test_supervision_config_defaults() {
let cfg = SupervisionConfig::default();
assert_eq!(cfg.max_attempts, Some(5));
assert_eq!(cfg.initial_delay, Duration::from_secs(1));
assert_eq!(cfg.backoff_multiplier, 2.0);
assert_eq!(cfg.max_delay, Duration::from_secs(60));
}
#[test]
fn test_supervision_config_infinite() {
let cfg = SupervisionConfig {
max_attempts: None,
..Default::default()
};
assert!(cfg.max_attempts.is_none());
}
#[test]
fn test_supervision_config_next_delay_growth() {
let cfg = SupervisionConfig::default();
let d1 = cfg.next_delay(1); let d2 = cfg.next_delay(2); let d3 = cfg.next_delay(3); assert_eq!(d1, Duration::from_secs(1));
assert_eq!(d2, Duration::from_secs(2));
assert_eq!(d3, Duration::from_secs(4));
}
#[test]
fn test_supervision_config_next_delay_capped() {
let cfg = SupervisionConfig {
max_delay: Duration::from_secs(5),
..Default::default()
};
let d = cfg.next_delay(10); assert_eq!(d, Duration::from_secs(5));
}
#[test]
fn test_next_delay_attempt_zero_returns_initial_delay() {
let cfg = SupervisionConfig::default();
let d = cfg.next_delay(0);
assert_eq!(d, cfg.initial_delay);
}
}