grafos_leasekit/
backoff.rs1#[derive(Debug, Clone)]
11pub struct Backoff {
12 initial_delay_secs: u64,
13 max_delay_secs: u64,
14 current_delay_secs: u64,
15}
16
17impl Backoff {
18 pub fn new(initial_delay_secs: u64, max_delay_secs: u64) -> Self {
21 let initial = initial_delay_secs.max(1);
22 Backoff {
23 initial_delay_secs: initial,
24 max_delay_secs: max_delay_secs.max(initial),
25 current_delay_secs: initial,
26 }
27 }
28
29 pub fn next_delay(&mut self) -> u64 {
31 let delay = self.current_delay_secs;
32 self.current_delay_secs = self
33 .current_delay_secs
34 .saturating_mul(2)
35 .min(self.max_delay_secs);
36 delay
37 }
38
39 pub fn reset(&mut self) {
41 self.current_delay_secs = self.initial_delay_secs;
42 }
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48
49 #[test]
50 fn backoff_doubles_to_cap() {
51 let mut b = Backoff::new(1, 8);
52 assert_eq!(b.next_delay(), 1);
53 assert_eq!(b.next_delay(), 2);
54 assert_eq!(b.next_delay(), 4);
55 assert_eq!(b.next_delay(), 8);
56 assert_eq!(b.next_delay(), 8); assert_eq!(b.next_delay(), 8);
58 }
59
60 #[test]
61 fn backoff_reset() {
62 let mut b = Backoff::new(1, 16);
63 b.next_delay();
64 b.next_delay();
65 b.next_delay();
66 assert_eq!(b.next_delay(), 8);
67 b.reset();
68 assert_eq!(b.next_delay(), 1);
69 }
70
71 #[test]
72 fn backoff_min_initial_is_one() {
73 let b = Backoff::new(0, 10);
74 assert_eq!(b.initial_delay_secs, 1);
75 }
76
77 #[test]
78 fn backoff_max_at_least_initial() {
79 let b = Backoff::new(10, 3);
80 assert_eq!(b.max_delay_secs, 10);
81 }
82
83 #[test]
84 fn backoff_saturating_mul() {
85 let mut b = Backoff::new(1, u64::MAX);
86 for _ in 0..100 {
88 let _ = b.next_delay();
89 }
90 }
91}