ai_lib_rust/cache/
backend.rs1use async_trait::async_trait;
4use std::collections::HashMap;
5use std::sync::{Arc, RwLock};
6use std::time::{Duration, Instant};
7use super::key::CacheKey;
8use crate::Result;
9
10#[derive(Clone)]
11struct CacheEntry { data: Vec<u8>, created_at: Instant, ttl: Duration, last_accessed: Instant }
12
13impl CacheEntry {
14 fn new(data: Vec<u8>, ttl: Duration) -> Self { let now = Instant::now(); Self { data, created_at: now, ttl, last_accessed: now } }
15 fn is_expired(&self) -> bool { self.created_at.elapsed() > self.ttl }
16}
17
18#[async_trait]
19pub trait CacheBackend: Send + Sync {
20 async fn get(&self, key: &CacheKey) -> Result<Option<Vec<u8>>>;
21 async fn set(&self, key: &CacheKey, value: &[u8], ttl: Duration) -> Result<()>;
22 async fn delete(&self, key: &CacheKey) -> Result<bool>;
23 async fn exists(&self, key: &CacheKey) -> Result<bool>;
24 async fn clear(&self) -> Result<()>;
25 async fn len(&self) -> Result<usize>;
26 fn name(&self) -> &'static str;
27}
28
29pub struct MemoryCache { entries: Arc<RwLock<HashMap<String, CacheEntry>>>, max_entries: usize }
30
31impl MemoryCache {
32 pub fn new(max_entries: usize) -> Self { Self { entries: Arc::new(RwLock::new(HashMap::new())), max_entries } }
33 fn evict_if_needed(&self, entries: &mut HashMap<String, CacheEntry>) {
34 entries.retain(|_, e| !e.is_expired());
35 while entries.len() >= self.max_entries {
36 let oldest = entries.iter().min_by_key(|(_, e)| e.last_accessed).map(|(k, _)| k.clone());
37 if let Some(k) = oldest { entries.remove(&k); } else { break; }
38 }
39 }
40}
41
42#[async_trait]
43impl CacheBackend for MemoryCache {
44 async fn get(&self, key: &CacheKey) -> Result<Option<Vec<u8>>> {
45 let mut entries = self.entries.write().unwrap();
46 if let Some(entry) = entries.get_mut(&key.hash) {
47 if entry.is_expired() { entries.remove(&key.hash); return Ok(None); }
48 entry.last_accessed = Instant::now();
49 return Ok(Some(entry.data.clone()));
50 }
51 Ok(None)
52 }
53 async fn set(&self, key: &CacheKey, value: &[u8], ttl: Duration) -> Result<()> {
54 let mut entries = self.entries.write().unwrap();
55 self.evict_if_needed(&mut entries);
56 entries.insert(key.hash.clone(), CacheEntry::new(value.to_vec(), ttl));
57 Ok(())
58 }
59 async fn delete(&self, key: &CacheKey) -> Result<bool> { Ok(self.entries.write().unwrap().remove(&key.hash).is_some()) }
60 async fn exists(&self, key: &CacheKey) -> Result<bool> {
61 let entries = self.entries.read().unwrap();
62 Ok(entries.get(&key.hash).map(|e| !e.is_expired()).unwrap_or(false))
63 }
64 async fn clear(&self) -> Result<()> { self.entries.write().unwrap().clear(); Ok(()) }
65 async fn len(&self) -> Result<usize> { Ok(self.entries.read().unwrap().values().filter(|e| !e.is_expired()).count()) }
66 fn name(&self) -> &'static str { "memory" }
67}
68
69pub struct NullCache;
70impl NullCache { pub fn new() -> Self { Self } }
71impl Default for NullCache { fn default() -> Self { Self::new() } }
72
73#[async_trait]
74impl CacheBackend for NullCache {
75 async fn get(&self, _: &CacheKey) -> Result<Option<Vec<u8>>> { Ok(None) }
76 async fn set(&self, _: &CacheKey, _: &[u8], _: Duration) -> Result<()> { Ok(()) }
77 async fn delete(&self, _: &CacheKey) -> Result<bool> { Ok(false) }
78 async fn exists(&self, _: &CacheKey) -> Result<bool> { Ok(false) }
79 async fn clear(&self) -> Result<()> { Ok(()) }
80 async fn len(&self) -> Result<usize> { Ok(0) }
81 fn name(&self) -> &'static str { "null" }
82}