agentic_comm/cache/
lru.rs1use std::collections::HashMap;
2use std::hash::Hash;
3use std::time::{Duration, Instant};
4use super::metrics::CacheMetrics;
5
6struct CacheEntry<V> { value: V, inserted_at: Instant, last_accessed: Instant }
7
8pub struct LruCache<K, V> {
9 store: HashMap<K, CacheEntry<V>>, max_size: usize, ttl: Duration, metrics: CacheMetrics,
10}
11
12impl<K: Eq + Hash + Clone, V: Clone> LruCache<K, V> {
13 pub fn new(max_size: usize, ttl: Duration) -> Self {
14 Self { store: HashMap::with_capacity(max_size), max_size, ttl, metrics: CacheMetrics::new() }
15 }
16 pub fn get(&mut self, key: &K) -> Option<V> {
17 let now = Instant::now();
18 if let Some(entry) = self.store.get_mut(key) {
19 if now.duration_since(entry.inserted_at) > self.ttl { self.store.remove(key); self.metrics.record_eviction(); self.metrics.record_miss(); return None; }
20 entry.last_accessed = now; self.metrics.record_hit(); return Some(entry.value.clone());
21 }
22 self.metrics.record_miss(); None
23 }
24 pub fn insert(&mut self, key: K, value: V) {
25 if self.store.len() >= self.max_size && !self.store.contains_key(&key) { self.evict_lru(); }
26 let now = Instant::now();
27 self.store.insert(key, CacheEntry { value, inserted_at: now, last_accessed: now });
28 self.metrics.set_size(self.store.len());
29 }
30 pub fn invalidate(&mut self, key: &K) -> bool {
31 let removed = self.store.remove(key).is_some();
32 if removed { self.metrics.record_eviction(); self.metrics.set_size(self.store.len()); }
33 removed
34 }
35 pub fn clear(&mut self) { self.store.clear(); self.metrics.set_size(0); }
36 pub fn contains(&self, key: &K) -> bool { self.store.get(key).map_or(false, |e| Instant::now().duration_since(e.inserted_at) <= self.ttl) }
37 pub fn len(&self) -> usize { self.store.len() }
38 pub fn is_empty(&self) -> bool { self.store.is_empty() }
39 pub fn metrics(&self) -> &CacheMetrics { &self.metrics }
40 fn evict_lru(&mut self) {
41 if let Some(key) = self.store.iter().min_by_key(|(_, e)| e.last_accessed).map(|(k, _)| k.clone()) { self.store.remove(&key); self.metrics.record_eviction(); }
42 }
43}