tryhard/
backoff_strategies.rsuse crate::RetryPolicy;
use std::time::Duration;
pub trait BackoffStrategy<'a, E> {
type Output;
fn delay(&mut self, attempt: u32, error: &'a E) -> Self::Output;
}
#[derive(Debug, Clone, Copy)]
pub struct NoBackoff;
impl<'a, E> BackoffStrategy<'a, E> for NoBackoff {
type Output = Duration;
#[inline]
fn delay(&mut self, _attempt: u32, _error: &'a E) -> Duration {
Duration::new(0, 0)
}
}
#[derive(Debug, Clone, Copy)]
pub struct ExponentialBackoff {
pub(crate) delay: Duration,
}
impl ExponentialBackoff {
pub fn new(initial_delay: Duration) -> Self {
Self {
delay: initial_delay,
}
}
}
impl<'a, E> BackoffStrategy<'a, E> for ExponentialBackoff {
type Output = Duration;
#[inline]
fn delay(&mut self, _attempt: u32, _error: &'a E) -> Duration {
let prev_delay = self.delay;
self.delay = self.delay.saturating_mul(2);
prev_delay
}
}
#[derive(Debug, Clone, Copy)]
pub struct FixedBackoff {
pub(crate) delay: Duration,
}
impl FixedBackoff {
pub fn new(initial_delay: Duration) -> Self {
Self {
delay: initial_delay,
}
}
}
impl<'a, E> BackoffStrategy<'a, E> for FixedBackoff {
type Output = Duration;
#[inline]
fn delay(&mut self, _attempt: u32, _error: &'a E) -> Duration {
self.delay
}
}
#[derive(Debug, Clone, Copy)]
pub struct LinearBackoff {
pub(crate) delay: Duration,
}
impl LinearBackoff {
pub fn new(initial_delay: Duration) -> Self {
Self {
delay: initial_delay,
}
}
}
impl<'a, E> BackoffStrategy<'a, E> for LinearBackoff {
type Output = Duration;
#[inline]
fn delay(&mut self, attempt: u32, _error: &'a E) -> Duration {
self.delay.saturating_mul(attempt)
}
}
impl<'a, F, E, T> BackoffStrategy<'a, E> for F
where
E: 'a,
F: FnMut(u32, &'a E) -> T,
T: Into<RetryPolicy>,
{
type Output = RetryPolicy;
#[inline]
fn delay(&mut self, attempt: u32, error: &'a E) -> RetryPolicy {
self(attempt, error).into()
}
}