hotshot_libp2p_networking/network/behaviours/
exponential_backoff.rs1use std::time::{Duration, Instant};
8
9#[derive(Debug, Clone, Eq, Hash, PartialEq)]
12pub struct ExponentialBackoff {
13 reset_val: Duration,
15 backoff_factor: u32,
17 timeout: Duration,
19 started: Option<Instant>,
21}
22
23impl ExponentialBackoff {
24 #[must_use]
26 pub fn new(backoff_factor: u32, next_timeout: Duration) -> Self {
27 ExponentialBackoff {
28 backoff_factor,
29 timeout: next_timeout * backoff_factor,
30 reset_val: next_timeout,
31 started: None,
32 }
33 }
34
35 pub fn reset(&mut self) {
37 self.timeout = self.reset_val;
38 }
39
40 pub fn start_next(&mut self, result: bool) {
46 if result {
48 self.timeout = self.reset_val;
49 self.started = Some(Instant::now());
50 }
51 else {
53 if let Some(r) = self.timeout.checked_mul(self.backoff_factor) {
55 self.timeout = r;
56 }
57 self.started = Some(Instant::now());
58 }
59 }
60
61 pub fn next_timeout(&mut self, result: bool) -> Duration {
63 let timeout = self.timeout;
64 self.start_next(result);
65 timeout
66 }
67 #[must_use]
69 pub fn is_expired(&self) -> bool {
70 if let Some(then) = self.started {
71 then.elapsed() > self.timeout
72 } else {
73 true
74 }
75 }
76 pub fn expire(&mut self) {
78 self.started = None;
79 }
80}
81
82impl Default for ExponentialBackoff {
83 fn default() -> Self {
84 Self {
85 reset_val: Duration::from_millis(500),
86 backoff_factor: 2,
87 timeout: Duration::from_millis(500),
88 started: None,
89 }
90 }
91}