Skip to main content

sz_orm_core/
cache.rs

1//! Cache abstraction layer
2//!
3//! Provides multi-level caching with memory support
4
5use crate::error::CacheError;
6use std::collections::HashMap;
7use std::sync::{Arc, RwLock};
8use std::time::{Duration, Instant};
9
10pub trait Cache: Send + Sync {
11    fn get(&self, key: &str) -> Result<Option<Vec<u8>>, CacheError>;
12    fn set(&self, key: &str, value: Vec<u8>, ttl: Option<Duration>) -> Result<(), CacheError>;
13    fn delete(&self, key: &str) -> Result<(), CacheError>;
14    fn clear(&self) -> Result<(), CacheError>;
15    fn exists(&self, key: &str) -> Result<bool, CacheError>;
16    fn expire(&self, key: &str, ttl: Duration) -> Result<(), CacheError>;
17    fn ttl(&self, key: &str) -> Result<Option<Duration>, CacheError>;
18}
19
20#[derive(Clone)]
21pub struct MemoryCache {
22    data: Arc<RwLock<HashMap<String, CacheEntry>>>,
23    default_ttl: Option<Duration>,
24}
25
26struct CacheEntry {
27    value: Vec<u8>,
28    expires_at: Option<Instant>,
29}
30
31impl MemoryCache {
32    pub fn new() -> Self {
33        Self {
34            data: Arc::new(RwLock::new(HashMap::new())),
35            default_ttl: None,
36        }
37    }
38
39    pub fn with_ttl(ttl: Duration) -> Self {
40        Self {
41            data: Arc::new(RwLock::new(HashMap::new())),
42            default_ttl: Some(ttl),
43        }
44    }
45}
46
47impl Default for MemoryCache {
48    fn default() -> Self {
49        Self::new()
50    }
51}
52
53impl Cache for MemoryCache {
54    fn get(&self, key: &str) -> Result<Option<Vec<u8>>, CacheError> {
55        let data = self.data.read()?;
56        if let Some(entry) = data.get(key) {
57            if let Some(expires_at) = entry.expires_at {
58                if expires_at <= Instant::now() {
59                    return Ok(None);
60                }
61            }
62            Ok(Some(entry.value.clone()))
63        } else {
64            Ok(None)
65        }
66    }
67
68    fn set(&self, key: &str, value: Vec<u8>, ttl: Option<Duration>) -> Result<(), CacheError> {
69        let expires_at = ttl.or(self.default_ttl).map(|d| Instant::now() + d);
70        let mut data = self.data.write()?;
71        data.insert(key.to_string(), CacheEntry { value, expires_at });
72        Ok(())
73    }
74
75    fn delete(&self, key: &str) -> Result<(), CacheError> {
76        let mut data = self.data.write()?;
77        data.remove(key);
78        Ok(())
79    }
80
81    fn clear(&self) -> Result<(), CacheError> {
82        let mut data = self.data.write()?;
83        data.clear();
84        Ok(())
85    }
86
87    fn exists(&self, key: &str) -> Result<bool, CacheError> {
88        let data = self.data.read()?;
89        if let Some(entry) = data.get(key) {
90            if let Some(expires_at) = entry.expires_at {
91                if expires_at <= Instant::now() {
92                    return Ok(false);
93                }
94            }
95            Ok(true)
96        } else {
97            Ok(false)
98        }
99    }
100
101    fn expire(&self, key: &str, ttl: Duration) -> Result<(), CacheError> {
102        let mut data = self.data.write()?;
103        if let Some(entry) = data.get_mut(key) {
104            entry.expires_at = Some(Instant::now() + ttl);
105            Ok(())
106        } else {
107            Err(CacheError::NotFound(key.to_string()))
108        }
109    }
110
111    fn ttl(&self, key: &str) -> Result<Option<Duration>, CacheError> {
112        let data = self.data.read()?;
113        if let Some(entry) = data.get(key) {
114            if let Some(expires_at) = entry.expires_at {
115                if expires_at <= Instant::now() {
116                    return Ok(None);
117                }
118                let remaining = expires_at.duration_since(Instant::now());
119                Ok(Some(remaining))
120            } else {
121                Ok(None)
122            }
123        } else {
124            Err(CacheError::NotFound(key.to_string()))
125        }
126    }
127}
128
129pub struct MultiLevelCache {
130    caches: Vec<Box<dyn Cache>>,
131}
132
133impl MultiLevelCache {
134    pub fn new() -> Self {
135        Self { caches: Vec::new() }
136    }
137
138    pub fn add_cache(mut self, cache: Box<dyn Cache>) -> Self {
139        self.caches.push(cache);
140        self
141    }
142}
143
144impl Default for MultiLevelCache {
145    fn default() -> Self {
146        Self::new()
147    }
148}
149
150impl Cache for MultiLevelCache {
151    fn get(&self, key: &str) -> Result<Option<Vec<u8>>, CacheError> {
152        for (i, cache) in self.caches.iter().enumerate() {
153            if let Ok(Some(value)) = cache.get(key) {
154                // 保留原始 TTL 信息:从命中的缓存层查询剩余 TTL,写回低层时使用
155                let ttl = cache.ttl(key).ok().flatten();
156                for j in 0..i {
157                    let _ = self.caches[j].set(key, value.clone(), ttl);
158                }
159                return Ok(Some(value));
160            }
161        }
162        Ok(None)
163    }
164
165    fn set(&self, key: &str, value: Vec<u8>, ttl: Option<Duration>) -> Result<(), CacheError> {
166        for cache in &self.caches {
167            cache.set(key, value.clone(), ttl)?;
168        }
169        Ok(())
170    }
171
172    fn delete(&self, key: &str) -> Result<(), CacheError> {
173        for cache in &self.caches {
174            cache.delete(key)?;
175        }
176        Ok(())
177    }
178
179    fn clear(&self) -> Result<(), CacheError> {
180        for cache in &self.caches {
181            cache.clear()?;
182        }
183        Ok(())
184    }
185
186    fn exists(&self, key: &str) -> Result<bool, CacheError> {
187        for cache in &self.caches {
188            if cache.exists(key)? {
189                return Ok(true);
190            }
191        }
192        Ok(false)
193    }
194
195    fn expire(&self, key: &str, ttl: Duration) -> Result<(), CacheError> {
196        for cache in &self.caches {
197            cache.expire(key, ttl)?;
198        }
199        Ok(())
200    }
201
202    fn ttl(&self, key: &str) -> Result<Option<Duration>, CacheError> {
203        if let Some(cache) = self.caches.first() {
204            cache.ttl(key)
205        } else {
206            Err(CacheError::NotFound("No caches configured".to_string()))
207        }
208    }
209}
210
211#[derive(Debug, Clone, Default)]
212pub struct CacheStats {
213    pub hits: u64,
214    pub misses: u64,
215    pub sets: u64,
216    pub deletes: u64,
217}
218
219#[cfg(test)]
220mod tests {
221    use super::*;
222
223    #[test]
224    fn test_memory_cache_set_get() {
225        let cache = MemoryCache::new();
226        cache.set("key1", b"value1".to_vec(), None).unwrap();
227        let val = cache.get("key1").unwrap();
228        assert_eq!(val, Some(b"value1".to_vec()));
229    }
230
231    #[test]
232    fn test_memory_cache_delete() {
233        let cache = MemoryCache::new();
234        cache.set("key1", b"value1".to_vec(), None).unwrap();
235        cache.delete("key1").unwrap();
236        let val = cache.get("key1").unwrap();
237        assert_eq!(val, None);
238    }
239
240    #[test]
241    fn test_memory_cache_exists() {
242        let cache = MemoryCache::new();
243        cache.set("key1", b"value1".to_vec(), None).unwrap();
244        let exists = cache.exists("key1").unwrap();
245        assert!(exists);
246        let exists2 = cache.exists("nonexistent").unwrap();
247        assert!(!exists2);
248    }
249
250    #[test]
251    fn test_memory_cache_clear() {
252        let cache = MemoryCache::new();
253        cache.set("key1", b"value1".to_vec(), None).unwrap();
254        cache.set("key2", b"value2".to_vec(), None).unwrap();
255        cache.clear().unwrap();
256        let val = cache.get("key1").unwrap();
257        assert_eq!(val, None);
258    }
259
260    #[test]
261    fn test_memory_cache_with_ttl() {
262        let cache = MemoryCache::with_ttl(Duration::from_secs(1));
263        cache.set("key1", b"value1".to_vec(), None).unwrap();
264        let val = cache.get("key1").unwrap();
265        assert!(val.is_some());
266    }
267
268    #[test]
269    fn test_cache_stats() {
270        let stats = CacheStats::default();
271        assert_eq!(stats.hits, 0);
272        assert_eq!(stats.misses, 0);
273    }
274
275    #[test]
276    fn test_multi_level_cache() {
277        let cache1 = MemoryCache::new();
278        let cache2 = MemoryCache::new();
279        let multi = MultiLevelCache::new()
280            .add_cache(Box::new(cache1))
281            .add_cache(Box::new(cache2));
282
283        multi.set("key1", b"value1".to_vec(), None).unwrap();
284        let val = multi.get("key1").unwrap();
285        assert_eq!(val, Some(b"value1".to_vec()));
286
287        multi.delete("key1").unwrap();
288        let val = multi.get("key1").unwrap();
289        assert_eq!(val, None);
290    }
291}