ainl_compression/
cache.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub struct CacheTtlResult {
9 pub base_ttl_secs: u64,
10 pub consecutive_hits_same_key: u32,
11 pub effective_ttl_secs: u64,
12 pub hit_global_cap: bool,
14}
15
16const MAX_EFFECTIVE_TTL_SECS: u64 = 86_400;
17
18#[must_use]
23pub fn effective_ttl_with_hysteresis(
24 base_ttl_secs: u64,
25 consecutive_hits_same_key: u32,
26) -> CacheTtlResult {
27 let base = base_ttl_secs.max(1);
28 let hits = consecutive_hits_same_key.min(32);
29 let bump_pct: u64 = (hits as u64).min(10) * 10;
31 let numer = 100 + bump_pct;
32 let stretched = (base.saturating_mul(numer)) / 100;
33 let doubled_cap = stretched.min(base.saturating_mul(2));
34 let eff = doubled_cap.min(MAX_EFFECTIVE_TTL_SECS);
35 let hit_global_cap = eff == MAX_EFFECTIVE_TTL_SECS && doubled_cap > MAX_EFFECTIVE_TTL_SECS;
36 CacheTtlResult {
37 base_ttl_secs: base,
38 consecutive_hits_same_key: hits,
39 effective_ttl_secs: eff,
40 hit_global_cap,
41 }
42}
43
44#[must_use]
46pub fn cache_policy_summary() -> &'static str {
47 "Cache coordinator v0: same-key hit streak increases effective TTL by +10%/hit (max +100%), then min(2× base, 86400s)."
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53
54 #[test]
55 fn zero_hits_is_base() {
56 let r = effective_ttl_with_hysteresis(300, 0);
57 assert_eq!(r.effective_ttl_secs, 300);
58 assert!(!r.hit_global_cap);
59 }
60
61 #[test]
62 fn many_hits_double_then_cap() {
63 let r = effective_ttl_with_hysteresis(50_000, 100);
64 assert_eq!(r.effective_ttl_secs, 86_400);
65 assert!(r.hit_global_cap);
66 }
67}