oxcache/client/
mod.rs

1//! Copyright (c) 2025-2026, Kirky.X
2//!
3//! MIT License
4//!
5//! 该模块定义了缓存客户端的接口和实现。
6
7pub mod db_loader;
8pub mod l1;
9pub mod l2;
10pub mod two_level;
11
12use crate::error::Result;
13use async_trait::async_trait;
14use std::any::Any;
15
16use crate::serialization::Serializer;
17use serde::{de::DeserializeOwned, Serialize};
18use tracing::instrument;
19
20/// 缓存扩展特征
21///
22/// 提供类型安全的缓存操作接口
23#[async_trait]
24pub trait CacheExt: CacheOps {
25    /// 获取缓存值(反序列化)
26    #[instrument(skip(self), level = "debug")]
27    async fn get<T: DeserializeOwned + Send>(&self, key: &str) -> Result<Option<T>> {
28        let bytes = self.get_bytes(key).await?;
29        match bytes {
30            Some(data) => {
31                let val = self.serializer().deserialize(&data)?;
32                Ok(Some(val))
33            }
34            None => Ok(None),
35        }
36    }
37
38    /// 设置缓存值(序列化)
39    #[instrument(skip(self, value), level = "debug")]
40    async fn set<T: Serialize + Send + Sync>(
41        &self,
42        key: &str,
43        value: &T,
44        ttl: Option<u64>,
45    ) -> Result<()> {
46        let bytes = self.serializer().serialize(value)?;
47        self.set_bytes(key, bytes, ttl).await
48    }
49
50    /// 仅设置 L1 缓存(如果支持)
51    /// 注意:此实现默认行为是 set_bytes,因为 CacheOps 没有区分 L1/L2。
52    /// 如果需要真正的 L1-only,需要底层支持或使用 L1OnlyClient。
53    /// 这里我们为了兼容示例代码,提供默认实现,但实际可能需要扩展 CacheOps。
54    /// 然而,CacheOps 是基础 trait,L1/L2 控制应该由具体 Client 类型或配置决定。
55    /// 如果用户想要手动控制,应该使用 set_bytes 并自己处理逻辑,或者我们在 CacheOps 中增加方法。
56    /// 鉴于 PRD F3 "独立缓存层支持",可以通过 Client 类型实现。
57    /// 但示例代码中使用了 set_l1_only。
58    /// 我们这里先添加 set_l1_only 到 CacheExt,但行为可能只是 set。
59    /// 为了真正支持,我们需要在 CacheOps 中添加 set_l1_bytes 等,或者扩展 CacheExt 在特定实现中覆盖。
60    /// 但 CacheExt 是 trait default impl,无法访问私有字段。
61    ///
62    /// 既然 F3 已经实现(通过 L1OnlyClient),我们可以让用户获取特定类型的 client。
63    /// 但示例代码是在同一个 client 上调用 set_l1_only。这意味着 TwoLevelClient 应该支持这个。
64    ///
65    /// 让我们修改 CacheOps 增加 set_l1_bytes / set_l2_bytes 接口,默认实现可以是 no-op 或 fallback。
66    /// 或者,我们只在 CacheExt 中提供,但需要 CacheOps 支持。
67    ///
68    /// 考虑到接口稳定性,我们在 CacheOps 中添加 set_l1_bytes 和 set_l2_bytes,并在 TwoLevelClient 中实现。
69    #[instrument(skip(self, value), level = "debug")]
70    async fn set_l1_only<T: Serialize + Send + Sync>(
71        &self,
72        key: &str,
73        value: &T,
74        ttl: Option<u64>,
75    ) -> Result<()> {
76        let bytes = self.serializer().serialize(value)?;
77        self.set_l1_bytes(key, bytes, ttl).await
78    }
79
80    #[instrument(skip(self, value), level = "debug")]
81    async fn set_l2_only<T: Serialize + Send + Sync>(
82        &self,
83        key: &str,
84        value: &T,
85        ttl: Option<u64>,
86    ) -> Result<()> {
87        let bytes = self.serializer().serialize(value)?;
88        self.set_l2_bytes(key, bytes, ttl).await
89    }
90}
91
92impl<T: CacheOps + ?Sized> CacheExt for T {}
93
94/// 缓存操作特征
95///
96/// 定义缓存系统的基本操作接口
97#[async_trait]
98pub trait CacheOps: Send + Sync + Any {
99    /// 获取缓存值
100    ///
101    /// # 参数
102    ///
103    /// * `key` - 缓存键
104    ///
105    /// # 返回值
106    ///
107    /// 返回缓存值,如果不存在则返回None
108    async fn get_bytes(&self, key: &str) -> Result<Option<Vec<u8>>>;
109
110    /// 获取 L1 缓存值(字节)
111    async fn get_l1_bytes(&self, _key: &str) -> Result<Option<Vec<u8>>> {
112        Err(crate::error::CacheError::NotSupported(
113            "get_l1_bytes".to_string(),
114        ))
115    }
116
117    /// 获取 L2 缓存值(字节)
118    async fn get_l2_bytes(&self, _key: &str) -> Result<Option<Vec<u8>>> {
119        Err(crate::error::CacheError::NotSupported(
120            "get_l2_bytes".to_string(),
121        ))
122    }
123
124    /// 设置缓存值
125    ///
126    /// # 参数
127    ///
128    /// * `key` - 缓存键
129    /// * `value` - 缓存值
130    /// * `ttl` - 过期时间(秒),None表示使用默认值
131    ///
132    /// # 返回值
133    ///
134    /// 返回操作结果
135    async fn set_bytes(&self, key: &str, value: Vec<u8>, ttl: Option<u64>) -> Result<()>;
136
137    /// 设置 L1 缓存值(字节)
138    async fn set_l1_bytes(&self, _key: &str, _value: Vec<u8>, _ttl: Option<u64>) -> Result<()> {
139        Err(crate::error::CacheError::NotSupported(
140            "set_l1_bytes".to_string(),
141        ))
142    }
143
144    /// 设置 L2 缓存值(字节)
145    async fn set_l2_bytes(&self, _key: &str, _value: Vec<u8>, _ttl: Option<u64>) -> Result<()> {
146        Err(crate::error::CacheError::NotSupported(
147            "set_l2_bytes".to_string(),
148        ))
149    }
150
151    /// 尝试获取分布式锁
152    ///
153    /// # 参数
154    ///
155    /// * `key` - 锁的键
156    /// * `value` - 锁的值(通常是唯一标识符,用于释放锁)
157    /// * `ttl` - 锁的过期时间(秒)
158    ///
159    /// # 返回值
160    ///
161    /// 成功获取锁返回 true,否则返回 false
162    async fn lock(&self, _key: &str, _value: &str, _ttl: u64) -> Result<bool> {
163        Ok(false)
164    }
165
166    /// 释放分布式锁
167    ///
168    /// # 参数
169    ///
170    /// * `key` - 锁的键
171    /// * `value` - 锁的值(必须匹配才能释放)
172    ///
173    /// # 返回值
174    ///
175    /// 成功释放返回 true,否则返回 false(例如锁不存在或值不匹配)
176    async fn unlock(&self, _key: &str, _value: &str) -> Result<bool> {
177        Ok(false)
178    }
179
180    /// 删除缓存项
181    ///
182    /// # 参数
183    ///
184    /// * `key` - 缓存键
185    ///
186    /// # 返回值
187    ///
188    /// 返回操作结果
189    async fn delete(&self, key: &str) -> Result<()>;
190
191    /// 获取序列化器
192    ///
193    /// 返回当前客户端使用的序列化器
194    fn serializer(&self) -> &crate::serialization::SerializerEnum;
195
196    /// 将 trait object 转换为 Any,用于向下转型
197    fn as_any(&self) -> &dyn Any;
198
199    /// 将 `Arc<Trait>` 转换为 `Arc<dyn Any>`,支持 Arc 下的向下转型
200    fn into_any_arc(self: std::sync::Arc<Self>) -> std::sync::Arc<dyn Any + Send + Sync>;
201
202    /// 清空 L1 缓存
203    ///
204    /// # 返回值
205    ///
206    /// 返回操作结果
207    async fn clear_l1(&self) -> Result<()> {
208        Err(crate::error::CacheError::NotSupported(
209            "clear_l1".to_string(),
210        ))
211    }
212
213    /// 清空 L2 缓存
214    ///
215    /// # 返回值
216    ///
217    /// 返回操作结果
218    async fn clear_l2(&self) -> Result<()> {
219        Err(crate::error::CacheError::NotSupported(
220            "clear_l2".to_string(),
221        ))
222    }
223
224    /// 清空 WAL 日志
225    ///
226    /// # 返回值
227    ///
228    /// 返回操作结果
229    async fn clear_wal(&self) -> Result<()> {
230        Err(crate::error::CacheError::NotSupported(
231            "clear_wal".to_string(),
232        ))
233    }
234
235    /// 优雅关闭客户端
236    ///
237    /// 关闭所有后台任务,释放资源
238    async fn shutdown(&self) -> Result<()> {
239        Ok(())
240    }
241}