1use super::Error;
4use std::time::Duration;
5
6pub trait RetryPolicy {
7 fn retry(&self, error: &Error, last_retry: Option<(usize, Duration)>) -> Option<Duration>;
10
11 fn set_reconnection_time(&mut self, duration: Duration);
13}
14
15#[derive(Debug, Clone)]
17pub struct ExponentialBackoff {
18 pub start: Duration,
20 pub factor: f64,
22 pub max_duration: Option<Duration>,
24 pub max_retries: Option<usize>,
26}
27
28impl ExponentialBackoff {
29 pub const fn new(
31 start: Duration,
32 factor: f64,
33 max_duration: Option<Duration>,
34 max_retries: Option<usize>,
35 ) -> Self {
36 Self {
37 start,
38 factor,
39 max_duration,
40 max_retries,
41 }
42 }
43}
44
45impl RetryPolicy for ExponentialBackoff {
46 fn retry(&self, _error: &Error, last_retry: Option<(usize, Duration)>) -> Option<Duration> {
47 if let Some((retry_num, last_duration)) = last_retry {
48 if self
49 .max_retries
50 .is_none_or(|max_retries| retry_num < max_retries)
51 {
52 let duration = last_duration.mul_f64(self.factor);
53 if let Some(max_duration) = self.max_duration {
54 Some(duration.min(max_duration))
55 } else {
56 Some(duration)
57 }
58 } else {
59 None
60 }
61 } else {
62 Some(self.start)
63 }
64 }
65 fn set_reconnection_time(&mut self, duration: Duration) {
66 self.start = duration;
67 if let Some(max_duration) = self.max_duration {
68 self.max_duration = Some(max_duration.max(duration))
69 }
70 }
71}
72
73#[derive(Debug, Clone)]
75pub struct Constant {
76 pub delay: Duration,
78 pub max_retries: Option<usize>,
80}
81
82impl Constant {
83 pub const fn new(delay: Duration, max_retries: Option<usize>) -> Self {
85 Self { delay, max_retries }
86 }
87}
88
89impl RetryPolicy for Constant {
90 fn retry(&self, _error: &Error, last_retry: Option<(usize, Duration)>) -> Option<Duration> {
91 if let Some((retry_num, _)) = last_retry {
92 if self
93 .max_retries
94 .is_none_or(|max_retries| retry_num < max_retries)
95 {
96 Some(self.delay)
97 } else {
98 None
99 }
100 } else {
101 Some(self.delay)
102 }
103 }
104 fn set_reconnection_time(&mut self, duration: Duration) {
105 self.delay = duration;
106 }
107}
108
109#[derive(Debug, Clone, Copy, Default)]
111pub struct Never;
112
113impl RetryPolicy for Never {
114 fn retry(&self, _error: &Error, _last_retry: Option<(usize, Duration)>) -> Option<Duration> {
115 None
116 }
117 fn set_reconnection_time(&mut self, _duration: Duration) {}
118}
119
120pub const DEFAULT_RETRY: ExponentialBackoff = ExponentialBackoff::new(
122 Duration::from_millis(300),
123 2.,
124 Some(Duration::from_secs(5)),
125 None,
126);