Skip to main content

wae_cache/
lib.rs

1//! WAE Cache - 缓存服务抽象层
2//!
3//! 提供统一的缓存能力抽象,支持多种缓存后端。
4//!
5//! 深度融合 tokio 运行时,所有 API 都是异步优先设计。
6//! 微服务架构友好,支持分布式缓存、过期策略等特性。
7
8#![warn(missing_docs)]
9
10use serde::{Serialize, de::DeserializeOwned};
11use std::{fmt, time::Duration};
12
13/// 缓存错误类型
14#[derive(Debug)]
15pub enum CacheError {
16    /// 连接失败
17    ConnectionFailed(String),
18
19    /// 序列化失败
20    SerializationFailed(String),
21
22    /// 反序列化失败
23    DeserializationFailed(String),
24
25    /// 键不存在
26    KeyNotFound(String),
27
28    /// 操作超时
29    Timeout(String),
30
31    /// 服务内部错误
32    Internal(String),
33}
34
35impl fmt::Display for CacheError {
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        match self {
38            CacheError::ConnectionFailed(msg) => write!(f, "Cache connection failed: {}", msg),
39            CacheError::SerializationFailed(msg) => write!(f, "Serialization failed: {}", msg),
40            CacheError::DeserializationFailed(msg) => write!(f, "Deserialization failed: {}", msg),
41            CacheError::KeyNotFound(msg) => write!(f, "Key not found: {}", msg),
42            CacheError::Timeout(msg) => write!(f, "Operation timeout: {}", msg),
43            CacheError::Internal(msg) => write!(f, "Cache internal error: {}", msg),
44        }
45    }
46}
47
48impl std::error::Error for CacheError {}
49
50/// 缓存操作结果类型
51pub type CacheResult<T> = Result<T, CacheError>;
52
53/// 缓存配置
54#[derive(Debug, Clone)]
55pub struct CacheConfig {
56    /// 缓存键前缀
57    pub key_prefix: String,
58    /// 默认过期时间
59    pub default_ttl: Option<Duration>,
60    /// 连接超时
61    pub connection_timeout: Duration,
62    /// 操作超时
63    pub operation_timeout: Duration,
64}
65
66impl Default for CacheConfig {
67    fn default() -> Self {
68        Self {
69            key_prefix: String::new(),
70            default_ttl: Some(Duration::from_secs(3600)),
71            connection_timeout: Duration::from_secs(5),
72            operation_timeout: Duration::from_secs(3),
73        }
74    }
75}
76
77/// 缓存服务核心 trait (dyn 兼容)
78///
79/// 定义统一的缓存操作接口,使用原始字节进行存储。
80/// 所有方法都是异步的,适配 tokio 运行时。
81#[async_trait::async_trait]
82pub trait CacheBackend: Send + Sync {
83    /// 获取缓存原始字节
84    async fn get_bytes(&self, key: &str) -> CacheResult<Option<Vec<u8>>>;
85
86    /// 设置缓存原始字节
87    async fn set_bytes(&self, key: &str, value: &[u8], ttl: Option<Duration>) -> CacheResult<()>;
88
89    /// 删除缓存键
90    async fn delete(&self, key: &str) -> CacheResult<bool>;
91
92    /// 检查键是否存在
93    async fn exists(&self, key: &str) -> CacheResult<bool>;
94
95    /// 设置键的过期时间
96    async fn expire(&self, key: &str, ttl: Duration) -> CacheResult<bool>;
97
98    /// 获取键的剩余过期时间
99    async fn ttl(&self, key: &str) -> CacheResult<Option<Duration>>;
100
101    /// 批量获取缓存原始字节
102    async fn mget_bytes(&self, keys: &[&str]) -> CacheResult<Vec<Option<Vec<u8>>>>;
103
104    /// 批量设置缓存原始字节
105    async fn mset_bytes(&self, items: &[(&str, &[u8])], ttl: Option<Duration>) -> CacheResult<()>;
106
107    /// 批量删除缓存键
108    async fn mdelete(&self, keys: &[&str]) -> CacheResult<u64>;
109
110    /// 自增操作
111    async fn incr(&self, key: &str, delta: i64) -> CacheResult<i64>;
112
113    /// 自减操作
114    async fn decr(&self, key: &str, delta: i64) -> CacheResult<i64>;
115
116    /// 清空当前命名空间下的所有缓存
117    async fn clear(&self) -> CacheResult<()>;
118
119    /// 获取缓存配置
120    fn config(&self) -> &CacheConfig;
121}
122
123/// 缓存服务 (提供泛型封装)
124pub struct CacheService {
125    backend: Box<dyn CacheBackend>,
126}
127
128impl CacheService {
129    /// 从后端创建缓存服务
130    pub fn new(backend: Box<dyn CacheBackend>) -> Self {
131        Self { backend }
132    }
133
134    /// 获取缓存值
135    pub async fn get<T: DeserializeOwned>(&self, key: &str) -> CacheResult<Option<T>> {
136        let bytes = self.backend.get_bytes(key).await?;
137        match bytes {
138            Some(data) => {
139                let value = serde_json::from_slice(&data).map_err(|e| CacheError::DeserializationFailed(e.to_string()))?;
140                Ok(Some(value))
141            }
142            None => Ok(None),
143        }
144    }
145
146    /// 设置缓存值
147    pub async fn set<T: Serialize + ?Sized>(&self, key: &str, value: &T, ttl: Option<Duration>) -> CacheResult<()> {
148        let data = serde_json::to_vec(value).map_err(|e| CacheError::SerializationFailed(e.to_string()))?;
149        self.backend.set_bytes(key, &data, ttl).await
150    }
151
152    /// 删除缓存键
153    pub async fn delete(&self, key: &str) -> CacheResult<bool> {
154        self.backend.delete(key).await
155    }
156
157    /// 检查键是否存在
158    pub async fn exists(&self, key: &str) -> CacheResult<bool> {
159        self.backend.exists(key).await
160    }
161
162    /// 设置键的过期时间
163    pub async fn expire(&self, key: &str, ttl: Duration) -> CacheResult<bool> {
164        self.backend.expire(key, ttl).await
165    }
166
167    /// 获取键的剩余过期时间
168    pub async fn ttl(&self, key: &str) -> CacheResult<Option<Duration>> {
169        self.backend.ttl(key).await
170    }
171
172    /// 批量获取缓存值
173    pub async fn mget<T: DeserializeOwned>(&self, keys: &[&str]) -> CacheResult<Vec<Option<T>>> {
174        let bytes_list = self.backend.mget_bytes(keys).await?;
175        let mut results = Vec::with_capacity(bytes_list.len());
176        for bytes in bytes_list {
177            match bytes {
178                Some(data) => {
179                    let value = serde_json::from_slice(&data).map_err(|e| CacheError::DeserializationFailed(e.to_string()))?;
180                    results.push(Some(value));
181                }
182                None => results.push(None),
183            }
184        }
185        Ok(results)
186    }
187
188    /// 批量设置缓存值
189    pub async fn mset<T: Serialize + ?Sized>(&self, items: &[(&str, &T)], ttl: Option<Duration>) -> CacheResult<()> {
190        let byte_items: Vec<(&str, Vec<u8>)> = items
191            .iter()
192            .map(|(k, v)| {
193                let data = serde_json::to_vec(v).map_err(|e| CacheError::SerializationFailed(e.to_string()))?;
194                Ok((*k, data))
195            })
196            .collect::<CacheResult<_>>()?;
197
198        let refs: Vec<(&str, &[u8])> = byte_items.iter().map(|(k, v)| (*k, v.as_slice())).collect();
199        self.backend.mset_bytes(&refs, ttl).await
200    }
201
202    /// 批量删除缓存键
203    pub async fn mdelete(&self, keys: &[&str]) -> CacheResult<u64> {
204        self.backend.mdelete(keys).await
205    }
206
207    /// 自增操作
208    pub async fn incr(&self, key: &str, delta: i64) -> CacheResult<i64> {
209        self.backend.incr(key, delta).await
210    }
211
212    /// 自减操作
213    pub async fn decr(&self, key: &str, delta: i64) -> CacheResult<i64> {
214        self.backend.decr(key, delta).await
215    }
216
217    /// 清空缓存
218    pub async fn clear(&self) -> CacheResult<()> {
219        self.backend.clear().await
220    }
221
222    /// 获取配置
223    pub fn config(&self) -> &CacheConfig {
224        self.backend.config()
225    }
226
227    /// 构建带前缀的完整键
228    pub fn build_key(&self, key: &str) -> String {
229        let config = self.config();
230        if config.key_prefix.is_empty() { key.to_string() } else { format!("{}:{}", config.key_prefix, key) }
231    }
232}
233
234/// 内存缓存实现
235pub mod memory {
236    use super::*;
237    use std::{collections::HashMap, sync::Arc};
238    use tokio::{sync::RwLock, time::Instant};
239
240    /// 缓存条目
241    struct CacheEntry {
242        data: Vec<u8>,
243        expires_at: Option<Instant>,
244    }
245
246    impl CacheEntry {
247        fn is_expired(&self) -> bool {
248            self.expires_at.map(|exp| Instant::now() >= exp).unwrap_or(false)
249        }
250    }
251
252    /// 内存缓存后端
253    pub struct MemoryCacheBackend {
254        config: CacheConfig,
255        store: Arc<RwLock<HashMap<String, CacheEntry>>>,
256    }
257
258    impl MemoryCacheBackend {
259        /// 创建新的内存缓存实例
260        pub fn new(config: CacheConfig) -> Self {
261            Self { config, store: Arc::new(RwLock::new(HashMap::new())) }
262        }
263
264        fn build_key(&self, key: &str) -> String {
265            if self.config.key_prefix.is_empty() { key.to_string() } else { format!("{}:{}", self.config.key_prefix, key) }
266        }
267    }
268
269    #[async_trait::async_trait]
270    impl CacheBackend for MemoryCacheBackend {
271        async fn get_bytes(&self, key: &str) -> CacheResult<Option<Vec<u8>>> {
272            let full_key = self.build_key(key);
273            let store = self.store.read().await;
274
275            if let Some(entry) = store.get(&full_key) {
276                if entry.is_expired() {
277                    return Ok(None);
278                }
279                return Ok(Some(entry.data.clone()));
280            }
281            Ok(None)
282        }
283
284        async fn set_bytes(&self, key: &str, value: &[u8], ttl: Option<Duration>) -> CacheResult<()> {
285            let full_key = self.build_key(key);
286            let effective_ttl = ttl.or(self.config.default_ttl);
287            let expires_at = effective_ttl.map(|d| Instant::now() + d);
288
289            let entry = CacheEntry { data: value.to_vec(), expires_at };
290            let mut store = self.store.write().await;
291            store.insert(full_key, entry);
292            Ok(())
293        }
294
295        async fn delete(&self, key: &str) -> CacheResult<bool> {
296            let full_key = self.build_key(key);
297            let mut store = self.store.write().await;
298            Ok(store.remove(&full_key).is_some())
299        }
300
301        async fn exists(&self, key: &str) -> CacheResult<bool> {
302            let full_key = self.build_key(key);
303            let store = self.store.read().await;
304            if let Some(entry) = store.get(&full_key) {
305                return Ok(!entry.is_expired());
306            }
307            Ok(false)
308        }
309
310        async fn expire(&self, key: &str, ttl: Duration) -> CacheResult<bool> {
311            let full_key = self.build_key(key);
312            let mut store = self.store.write().await;
313            if let Some(entry) = store.get_mut(&full_key) {
314                if entry.is_expired() {
315                    return Ok(false);
316                }
317                entry.expires_at = Some(Instant::now() + ttl);
318                return Ok(true);
319            }
320            Ok(false)
321        }
322
323        async fn ttl(&self, key: &str) -> CacheResult<Option<Duration>> {
324            let full_key = self.build_key(key);
325            let store = self.store.read().await;
326            if let Some(entry) = store.get(&full_key) {
327                if entry.is_expired() {
328                    return Ok(None);
329                }
330                if let Some(expires_at) = entry.expires_at {
331                    let now = Instant::now();
332                    if expires_at > now {
333                        return Ok(Some(expires_at - now));
334                    }
335                }
336            }
337            Ok(None)
338        }
339
340        async fn mget_bytes(&self, keys: &[&str]) -> CacheResult<Vec<Option<Vec<u8>>>> {
341            let mut results = Vec::with_capacity(keys.len());
342            for key in keys {
343                results.push(self.get_bytes(key).await?);
344            }
345            Ok(results)
346        }
347
348        async fn mset_bytes(&self, items: &[(&str, &[u8])], ttl: Option<Duration>) -> CacheResult<()> {
349            for (key, value) in items {
350                self.set_bytes(key, value, ttl).await?;
351            }
352            Ok(())
353        }
354
355        async fn mdelete(&self, keys: &[&str]) -> CacheResult<u64> {
356            let mut count = 0u64;
357            for key in keys {
358                if self.delete(key).await? {
359                    count += 1;
360                }
361            }
362            Ok(count)
363        }
364
365        async fn incr(&self, key: &str, delta: i64) -> CacheResult<i64> {
366            let full_key = self.build_key(key);
367            let mut store = self.store.write().await;
368
369            let entry = store.entry(full_key.clone()).or_insert(CacheEntry { data: b"0".to_vec(), expires_at: None });
370
371            let mut value: i64 = String::from_utf8_lossy(&entry.data).parse().unwrap_or(0);
372            value += delta;
373            entry.data = value.to_string().into_bytes();
374            Ok(value)
375        }
376
377        async fn decr(&self, key: &str, delta: i64) -> CacheResult<i64> {
378            self.incr(key, -delta).await
379        }
380
381        async fn clear(&self) -> CacheResult<()> {
382            let mut store = self.store.write().await;
383            if self.config.key_prefix.is_empty() {
384                store.clear();
385            }
386            else {
387                let prefix = format!("{}:", self.config.key_prefix);
388                store.retain(|k, _| !k.starts_with(&prefix));
389            }
390            Ok(())
391        }
392
393        fn config(&self) -> &CacheConfig {
394            &self.config
395        }
396    }
397}
398
399/// 便捷函数:创建内存缓存服务
400pub fn memory_cache(config: CacheConfig) -> CacheService {
401    CacheService::new(Box::new(memory::MemoryCacheBackend::new(config)))
402}