synaps_cli/extensions/runtime/
restart.rs1use std::time::Duration;
4
5#[derive(Debug, Clone, Copy)]
6pub struct RestartPolicy {
7 pub max_attempts: u32,
8 pub base_delay: Duration,
9 pub max_delay: Duration,
10 pub multiplier: f32,
12}
13
14impl Default for RestartPolicy {
15 fn default() -> Self {
16 Self {
17 max_attempts: 3,
18 base_delay: Duration::from_millis(250),
19 max_delay: Duration::from_secs(5),
20 multiplier: 2.0,
21 }
22 }
23}
24
25impl RestartPolicy {
26 pub fn delay_for_attempt(&self, attempt: u32) -> Option<Duration> {
29 if attempt == 0 || attempt > self.max_attempts {
30 return None;
31 }
32 let exp = (attempt - 1) as i32;
33 let factor = self.multiplier.powi(exp);
34 let nanos = (self.base_delay.as_nanos() as f64 * factor as f64)
35 .min(self.max_delay.as_nanos() as f64) as u64;
36 Some(Duration::from_nanos(nanos))
37 }
38}
39
40#[cfg(test)]
41mod tests {
42 use super::*;
43
44 #[test]
45 fn default_policy_attempt_1_returns_base_delay() {
46 let p = RestartPolicy::default();
47 assert_eq!(p.delay_for_attempt(1), Some(Duration::from_millis(250)));
48 }
49
50 #[test]
51 fn attempt_2_doubles_base() {
52 let p = RestartPolicy::default();
53 assert_eq!(p.delay_for_attempt(2), Some(Duration::from_millis(500)));
54 }
55
56 #[test]
57 fn attempt_capped_at_max_delay() {
58 let p = RestartPolicy {
59 max_attempts: 5,
60 base_delay: Duration::from_secs(1),
61 max_delay: Duration::from_secs(2),
62 multiplier: 10.0,
63 };
64 assert_eq!(p.delay_for_attempt(2), Some(Duration::from_secs(2)));
65 }
66
67 #[test]
68 fn attempt_zero_returns_none() {
69 let p = RestartPolicy::default();
70 assert_eq!(p.delay_for_attempt(0), None);
71 }
72
73 #[test]
74 fn attempt_beyond_max_returns_none() {
75 let p = RestartPolicy::default();
76 assert_eq!(p.delay_for_attempt(p.max_attempts + 1), None);
77 }
78
79 #[test]
80 fn custom_multiplier() {
81 let p = RestartPolicy {
82 max_attempts: 5,
83 base_delay: Duration::from_millis(100),
84 max_delay: Duration::from_secs(60),
85 multiplier: 3.0,
86 };
87 assert_eq!(p.delay_for_attempt(3), Some(Duration::from_millis(900)));
89 }
90
91 #[test]
92 fn default_max_attempts_is_three() {
93 assert_eq!(RestartPolicy::default().max_attempts, 3);
94 }
95}