Skip to main content

ainl_compression/
cache.rs

1//! Cache-aware **TTL coordination** hints for compression-related caches.
2//!
3//! Hosts attach real storage; this module only models **hysteresis** on repeated hits so
4//! hot keys do not thrash TTL without unbounded growth.
5
6/// Result of [`effective_ttl_with_hysteresis`].
7#[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    /// `true` when the global safety cap applied.
13    pub hit_global_cap: bool,
14}
15
16const MAX_EFFECTIVE_TTL_SECS: u64 = 86_400;
17
18/// Stretch effective TTL modestly on repeated access to the same logical key, capped at **2× base**
19/// and at [`MAX_EFFECTIVE_TTL_SECS`].
20///
21/// `consecutive_hits_same_key`: monotonic counter reset by the host when the key changes.
22#[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    // +10% per hit for up to 10 stacked hits → up to 2× base before cap.
30    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/// One-line description for operator CLIs / docs.
45#[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}