telemetry_kit/sync/
retry.rs1use rand::Rng;
4use std::time::Duration;
5
6#[derive(Debug, Clone)]
8pub struct RetryStrategy {
9 max_retries: u32,
10 base_delay_ms: u64,
11}
12
13impl RetryStrategy {
14 pub fn new(max_retries: u32, base_delay_ms: u64) -> Self {
20 Self {
21 max_retries,
22 base_delay_ms,
23 }
24 }
25
26 pub fn default_strategy() -> Self {
28 Self::new(5, 1000)
29 }
30
31 pub fn delay_for(&self, retry_count: u32) -> Duration {
42 let exponential_delay = self.base_delay_ms * 2_u64.pow(retry_count);
43 let jitter = rand::thread_rng().gen_range(0..1000); Duration::from_millis(exponential_delay + jitter)
46 }
47
48 pub fn should_retry(&self, retry_count: u32) -> bool {
50 retry_count < self.max_retries
51 }
52
53 pub fn max_retries(&self) -> u32 {
55 self.max_retries
56 }
57}
58
59impl Default for RetryStrategy {
60 fn default() -> Self {
61 Self::default_strategy()
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68
69 #[test]
70 fn test_retry_delay() {
71 let strategy = RetryStrategy::new(5, 1000);
72
73 let delay0 = strategy.delay_for(0);
75 assert!(delay0.as_millis() >= 1000 && delay0.as_millis() < 2000);
76
77 let delay1 = strategy.delay_for(1);
79 assert!(delay1.as_millis() >= 2000 && delay1.as_millis() < 3000);
80
81 let delay2 = strategy.delay_for(2);
83 assert!(delay2.as_millis() >= 4000 && delay2.as_millis() < 5000);
84 }
85
86 #[test]
87 fn test_should_retry() {
88 let strategy = RetryStrategy::new(3, 1000);
89
90 assert!(strategy.should_retry(0));
91 assert!(strategy.should_retry(1));
92 assert!(strategy.should_retry(2));
93 assert!(!strategy.should_retry(3));
94 assert!(!strategy.should_retry(4));
95 }
96
97 #[test]
98 fn test_default_strategy() {
99 let strategy = RetryStrategy::default();
100 assert_eq!(strategy.max_retries(), 5);
101 }
102}