crispy_stream_checker/
backoff.rs1use std::time::Duration;
16
17use serde::{Deserialize, Serialize};
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
21#[serde(rename_all = "lowercase")]
22pub enum BackoffStrategy {
23 None,
25 #[default]
27 Linear,
28 Exponential,
30}
31
32impl BackoffStrategy {
33 pub fn delay(&self, attempt_index: u32) -> Duration {
40 match self {
41 BackoffStrategy::None => Duration::ZERO,
42 BackoffStrategy::Linear => {
43 let secs = (attempt_index + 1).min(10);
44 Duration::from_secs(u64::from(secs))
45 }
46 BackoffStrategy::Exponential => {
47 let secs = 2u64.saturating_pow(attempt_index).min(30);
48 Duration::from_secs(secs)
49 }
50 }
51 }
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57
58 #[test]
59 fn no_backoff_always_zero() {
60 for attempt in 0..10 {
61 assert_eq!(BackoffStrategy::None.delay(attempt), Duration::ZERO);
62 }
63 }
64
65 #[test]
66 fn linear_backoff_increments_by_one() {
67 assert_eq!(BackoffStrategy::Linear.delay(0), Duration::from_secs(1));
68 assert_eq!(BackoffStrategy::Linear.delay(1), Duration::from_secs(2));
69 assert_eq!(BackoffStrategy::Linear.delay(2), Duration::from_secs(3));
70 }
71
72 #[test]
73 fn linear_backoff_caps_at_10() {
74 assert_eq!(BackoffStrategy::Linear.delay(9), Duration::from_secs(10));
75 assert_eq!(BackoffStrategy::Linear.delay(15), Duration::from_secs(10));
76 assert_eq!(BackoffStrategy::Linear.delay(100), Duration::from_secs(10));
77 }
78
79 #[test]
80 fn exponential_backoff_doubles() {
81 assert_eq!(
82 BackoffStrategy::Exponential.delay(0),
83 Duration::from_secs(1)
84 );
85 assert_eq!(
86 BackoffStrategy::Exponential.delay(1),
87 Duration::from_secs(2)
88 );
89 assert_eq!(
90 BackoffStrategy::Exponential.delay(2),
91 Duration::from_secs(4)
92 );
93 assert_eq!(
94 BackoffStrategy::Exponential.delay(3),
95 Duration::from_secs(8)
96 );
97 }
98
99 #[test]
100 fn exponential_backoff_caps_at_30() {
101 assert_eq!(
103 BackoffStrategy::Exponential.delay(5),
104 Duration::from_secs(30)
105 );
106 assert_eq!(
107 BackoffStrategy::Exponential.delay(10),
108 Duration::from_secs(30)
109 );
110 }
111}