tryhard/
backoff_strategies.rs1use crate::RetryPolicy;
4use std::time::Duration;
5
6pub trait BackoffStrategy<'a, E> {
8 type Output;
13
14 fn delay(&mut self, attempt: u32, error: &'a E) -> Self::Output;
17}
18
19#[derive(Debug, Clone, Copy)]
22pub struct NoBackoff;
23
24impl<'a, E> BackoffStrategy<'a, E> for NoBackoff {
25 type Output = Duration;
26
27 #[inline]
28 fn delay(&mut self, _attempt: u32, _error: &'a E) -> Duration {
29 Duration::new(0, 0)
30 }
31}
32
33#[derive(Debug, Clone, Copy)]
35pub struct ExponentialBackoff {
36 pub(crate) delay: Duration,
37}
38
39impl ExponentialBackoff {
40 pub fn new(initial_delay: Duration) -> Self {
42 Self {
43 delay: initial_delay,
44 }
45 }
46}
47
48impl<'a, E> BackoffStrategy<'a, E> for ExponentialBackoff {
49 type Output = Duration;
50
51 #[inline]
52 fn delay(&mut self, _attempt: u32, _error: &'a E) -> Duration {
53 let prev_delay = self.delay;
54 self.delay = self.delay.saturating_mul(2);
55 prev_delay
56 }
57}
58
59#[derive(Debug, Clone, Copy)]
61pub struct FixedBackoff {
62 pub(crate) delay: Duration,
63}
64
65impl FixedBackoff {
66 pub fn new(initial_delay: Duration) -> Self {
68 Self {
69 delay: initial_delay,
70 }
71 }
72}
73
74impl<'a, E> BackoffStrategy<'a, E> for FixedBackoff {
75 type Output = Duration;
76
77 #[inline]
78 fn delay(&mut self, _attempt: u32, _error: &'a E) -> Duration {
79 self.delay
80 }
81}
82
83#[derive(Debug, Clone, Copy)]
85pub struct LinearBackoff {
86 pub(crate) delay: Duration,
87}
88
89impl LinearBackoff {
90 pub fn new(initial_delay: Duration) -> Self {
92 Self {
93 delay: initial_delay,
94 }
95 }
96}
97
98impl<'a, E> BackoffStrategy<'a, E> for LinearBackoff {
99 type Output = Duration;
100
101 #[inline]
102 fn delay(&mut self, attempt: u32, _error: &'a E) -> Duration {
103 self.delay.saturating_mul(attempt)
104 }
105}
106
107impl<'a, F, E, T> BackoffStrategy<'a, E> for F
108where
109 E: 'a,
110 F: FnMut(u32, &'a E) -> T,
111 T: Into<RetryPolicy>,
112{
113 type Output = RetryPolicy;
114
115 #[inline]
116 fn delay(&mut self, attempt: u32, error: &'a E) -> RetryPolicy {
117 self(attempt, error).into()
118 }
119}