Skip to main content

lean_ctx/server/
reference_store.rs

1use std::collections::HashMap;
2use std::sync::{Mutex, OnceLock};
3use std::time::{Duration, Instant, SystemTime};
4
5struct RefEntry {
6    content: String,
7    created_at: Instant,
8    access_count: u32,
9}
10
11const MAX_ENTRIES: usize = 200;
12const TTL: Duration = Duration::from_mins(5);
13
14fn store_lock() -> &'static Mutex<HashMap<String, RefEntry>> {
15    static STORE: OnceLock<Mutex<HashMap<String, RefEntry>>> = OnceLock::new();
16    STORE.get_or_init(|| Mutex::new(HashMap::new()))
17}
18
19pub fn store(content: String) -> String {
20    let id = format!("ref_{}", generate_id());
21    let mut map = store_lock()
22        .lock()
23        .unwrap_or_else(std::sync::PoisonError::into_inner);
24
25    map.retain(|_, v| v.created_at.elapsed() < TTL);
26
27    while map.len() >= MAX_ENTRIES {
28        if let Some(oldest_key) = map
29            .iter()
30            .min_by_key(|(_, v)| v.created_at)
31            .map(|(k, _)| k.clone())
32        {
33            map.remove(&oldest_key);
34        } else {
35            break;
36        }
37    }
38
39    map.insert(
40        id.clone(),
41        RefEntry {
42            content,
43            created_at: Instant::now(),
44            access_count: 0,
45        },
46    );
47
48    id
49}
50
51pub fn resolve(id: &str) -> Option<String> {
52    let mut map = store_lock()
53        .lock()
54        .unwrap_or_else(std::sync::PoisonError::into_inner);
55    if let Some(entry) = map.get_mut(id) {
56        if entry.created_at.elapsed() < TTL {
57            entry.access_count += 1;
58            return Some(entry.content.clone());
59        }
60        map.remove(id);
61    }
62    None
63}
64
65pub fn stats() -> (usize, usize) {
66    let map = store_lock()
67        .lock()
68        .unwrap_or_else(std::sync::PoisonError::into_inner);
69    let total = map.len();
70    let total_bytes: usize = map.values().map(|v| v.content.len()).sum();
71    (total, total_bytes)
72}
73
74fn generate_id() -> String {
75    let ts = SystemTime::now()
76        .duration_since(SystemTime::UNIX_EPOCH)
77        .unwrap_or_default()
78        .as_nanos();
79    format!("{ts:x}")
80}