Skip to main content

backyard_core/
retry.rs

1use chrono::{DateTime, Duration, Utc};
2use std::time;
3
4pub fn next_retry_at(attempts: u32) -> DateTime<Utc> {
5    let base_secs: u64 = 10;
6    let cap_secs: u64 = 3600;
7
8    let backoff = base_secs
9        .saturating_mul(2u64.saturating_pow(attempts))
10        .min(cap_secs);
11
12    let jitter = rand::random::<u64>() % (backoff / 4 + 1);
13    let delay = time::Duration::from_secs(backoff + jitter);
14    Utc::now() + Duration::from_std(delay).unwrap_or_default()
15}
16
17#[cfg(test)]
18mod tests {
19    use super::*;
20
21    #[test]
22    fn test_exponential_growth() {
23        let t0 = next_retry_at(0);
24        let t1 = next_retry_at(1);
25        let t2 = next_retry_at(2);
26
27        assert!(t1 > t0);
28        assert!(t2 > t1);
29    }
30
31    #[test]
32    fn test_backoff_cap() {
33        let t100 = next_retry_at(100);
34        let t101 = next_retry_at(101);
35
36        let diff = t101.signed_duration_since(t100);
37        assert!(diff.num_seconds() < 3600);
38    }
39}