grafos_leasekit/
policy.rs1#[derive(Debug, Clone, Copy)]
15pub struct RenewalPolicy {
16 pub renew_at_fraction: f64,
21
22 pub jitter_fraction: f64,
27
28 pub min_renew_secs: u64,
30
31 pub max_backoff_secs: u64,
33}
34
35impl Default for RenewalPolicy {
36 fn default() -> Self {
37 RenewalPolicy {
38 renew_at_fraction: 0.75,
39 jitter_fraction: 0.10,
40 min_renew_secs: 30,
41 max_backoff_secs: 5,
42 }
43 }
44}
45
46impl RenewalPolicy {
47 pub fn renewal_deadline(&self, created_at: u64, expires_at: u64, jitter_seed: u64) -> u64 {
53 if expires_at <= created_at {
54 return created_at;
55 }
56 let total_ttl = (expires_at - created_at) as f64;
57 let base_offset = total_ttl * self.renew_at_fraction;
58
59 let jitter_norm = ((jitter_seed % 1000) as f64 / 500.0) - 1.0;
61 let jitter = jitter_norm * self.jitter_fraction * total_ttl;
62
63 let offset = (base_offset + jitter).max(0.0).min(total_ttl);
64 created_at + offset as u64
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71
72 #[test]
73 fn default_policy_values() {
74 let p = RenewalPolicy::default();
75 assert!((p.renew_at_fraction - 0.75).abs() < f64::EPSILON);
76 assert!((p.jitter_fraction - 0.10).abs() < f64::EPSILON);
77 assert_eq!(p.min_renew_secs, 30);
78 assert_eq!(p.max_backoff_secs, 5);
79 }
80
81 #[test]
82 fn renewal_deadline_no_jitter() {
83 let p = RenewalPolicy {
84 renew_at_fraction: 0.75,
85 jitter_fraction: 0.0,
86 min_renew_secs: 30,
87 max_backoff_secs: 5,
88 };
89 let deadline = p.renewal_deadline(1000, 1100, 0);
91 assert_eq!(deadline, 1075);
92 }
93
94 #[test]
95 fn renewal_deadline_with_jitter_bounds() {
96 let p = RenewalPolicy {
97 renew_at_fraction: 0.75,
98 jitter_fraction: 0.10,
99 min_renew_secs: 30,
100 max_backoff_secs: 5,
101 };
102 for seed in 0..1000 {
105 let deadline = p.renewal_deadline(1000, 1100, seed);
106 assert!(
107 (1065..=1085).contains(&deadline),
108 "seed={seed} deadline={deadline}"
109 );
110 }
111 }
112
113 #[test]
114 fn renewal_deadline_degenerate_ttl() {
115 let p = RenewalPolicy::default();
116 assert_eq!(p.renewal_deadline(100, 100, 0), 100);
118 assert_eq!(p.renewal_deadline(200, 100, 0), 200);
119 }
120}