Skip to main content

lean_ctx/core/
context_gc.rs

1use crate::core::cache::SessionCache;
2
3const PRESSURE_THRESHOLD_TOKENS: usize = 50_000;
4const TARGET_AFTER_GC_TOKENS: usize = 35_000;
5
6#[allow(dead_code)]
7pub struct GcResult {
8    pub tokens_freed: usize,
9    pub tokens_before: usize,
10    pub tokens_after: usize,
11}
12
13pub(crate) fn should_run_gc(cache: &SessionCache) -> bool {
14    cache.total_cached_tokens() > PRESSURE_THRESHOLD_TOKENS
15}
16
17pub(crate) fn run_gc(cache: &mut SessionCache) -> GcResult {
18    let tokens_before = cache.total_cached_tokens();
19    if tokens_before <= PRESSURE_THRESHOLD_TOKENS {
20        return GcResult {
21            tokens_freed: 0,
22            tokens_before,
23            tokens_after: tokens_before,
24        };
25    }
26
27    cache.evict_to_budget(TARGET_AFTER_GC_TOKENS);
28    let tokens_after = cache.total_cached_tokens();
29
30    GcResult {
31        tokens_freed: tokens_before.saturating_sub(tokens_after),
32        tokens_before,
33        tokens_after,
34    }
35}
36
37pub fn maybe_gc(cache: &mut SessionCache) -> Option<GcResult> {
38    if should_run_gc(cache) {
39        Some(run_gc(cache))
40    } else {
41        None
42    }
43}
44
45#[cfg(test)]
46mod tests {
47    use super::*;
48
49    #[test]
50    fn gc_does_not_run_below_threshold() {
51        let cache = SessionCache::new();
52        assert!(!should_run_gc(&cache));
53    }
54}