use crate::compat::Duration;
use crate::state::RetryState;
use super::Wait;
use super::math::{
clamp_exponential_base, pow_nonnegative_f64, saturating_duration_mul,
saturating_duration_mul_f64,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct WaitFixed {
duration: Duration,
}
#[must_use]
pub fn fixed(dur: Duration) -> WaitFixed {
WaitFixed { duration: dur }
}
impl Wait for WaitFixed {
fn next_wait(&self, _state: &RetryState) -> Duration {
self.duration
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct WaitLinear {
initial: Duration,
increment: Duration,
}
#[must_use]
pub fn linear(initial: Duration, increment: Duration) -> WaitLinear {
WaitLinear { initial, increment }
}
impl Wait for WaitLinear {
fn next_wait(&self, state: &RetryState) -> Duration {
let multiplier = state.attempt.saturating_sub(1);
let step = saturating_duration_mul(self.increment, multiplier);
self.initial.saturating_add(step)
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct WaitExponential {
initial: Duration,
base: f64,
}
const DEFAULT_EXPONENTIAL_BASE: f64 = 2.0;
#[must_use]
pub fn exponential(initial: Duration) -> WaitExponential {
WaitExponential {
initial,
base: DEFAULT_EXPONENTIAL_BASE,
}
}
impl WaitExponential {
#[must_use]
pub fn base(mut self, base: f64) -> Self {
self.base = clamp_exponential_base(base);
self
}
}
impl Wait for WaitExponential {
fn next_wait(&self, state: &RetryState) -> Duration {
let exponent = state.attempt.saturating_sub(1);
let multiplier = pow_nonnegative_f64(self.base, exponent);
saturating_duration_mul_f64(self.initial, multiplier)
}
}