Skip to main content

sz_rust_core/
cache.rs

1//! SZ-Rust Cache facade — 对齐 PHP `think\facade\Cache`
2//!
3//! 缓存 facade 模块。
4//!
5//! ## PHP 对齐
6//!
7//! ### 1. 静态 API 风格(对齐 PHP `think\facade\Cache::__callStatic`)
8//!
9//! PHP `think\facade\Cache` 是 facade,所有静态方法通过 `__callStatic` 转发到
10//! `think\Cache`(Manager)实例的对应方法。
11//!
12//! Rust 端通过全局 `OnceLock<Cache>` + `Cache::default_instance()` 提供"伪静态"
13//! API;调用方也可以创建独立 `Cache` 实例用于测试隔离。
14//!
15//! ### 2. 驱动管理器(对齐 PHP `think\Cache extends Manager`)
16//!
17//! PHP `think\Cache` 继承 `think\Manager`,通过 `$namespace = '\\think\\cache\\driver\\'`
18//! 和 `createDriver(array $config)` 创建驱动实例,并缓存到 `$this->drivers[]`。
19//!
20//! Rust 端通过 `CacheManager` + `CacheDriver` trait 提供等价能力:
21//! - `register_store(name, driver)`:注册命名驱动
22//! - `store(name)`:获取命名驱动
23//! - `default_store()`:获取默认驱动
24//!
25//! ### 3. 序列化策略(对齐 PHP `is_numeric` 短路)
26//!
27//! PHP `think\cache\Driver::serialize($data)` 第 612 行:
28//!
29//! ```php
30//! public function serialize($data): string
31//! {
32//!     if (is_numeric($data)) {
33//!         return (string) $data;
34//!     }
35//!     return serialize($data);
36//! }
37//! ```
38//!
39//! PHP `think\cache\Driver::unserialize($data)` 第 623 行:
40//!
41//! ```php
42//! public function unserialize($data)
43//! {
44//!     if (is_numeric($data)) {
45//!         return $data;  // ⚠️ 返回 string,而非 int(PHP 源码 bug)
46//!     }
47//!     return unserialize($data);
48//! }
49//! ```
50//!
51//! **PHP 源码 bug 复刻**:`unserialize` 对 `is_numeric` 的值返回 string,
52//! 而非还原为 int。本模块通过 `CacheValue::Number` 标记 + `get::<String>()`
53//! 返回 string 来复刻此行为。
54//!
55//! ### 4. `remember` 锁机制(对齐 PHP `think\cache\Driver::remember`)
56//!
57//! PHP `think\cache\Driver::remember` 第 287-310 行:
58//!
59//! ```php
60//! public function remember(string $name, callable $callback, $expire = null)
61//! {
62//!     if (($data = $this->get($name)) !== null) {
63//!         return $data;
64//!     }
65//!
66//!     $lockName = $name . '_lock';
67//!
68//!     // 抢锁
69//!     if ($this->has($lockName)) {
70//!         // 等待锁释放,200ms 轮询,5 秒超时
71//!         $startTime = microtime(true);
72//!         while ($this->has($lockName) && microtime(true) - $startTime < 5) {
73//!             usleep(200000);
74//!         }
75//!         // 锁释放后再次读取
76//!         if ($this->has($lockName)) {
77//!             // 超时仍未释放,直接调用 callback(防止永久阻塞)
78//!             return $callback();
79//!         }
80//!         $data = $this->get($name);
81//!         if ($data !== null) {
82//!             return $data;
83//!         }
84//!     }
85//!
86//!     // 抢到锁(无 TTL,PHP 源码 bug:锁不设过期时间)
87//!     $this->set($lockName, 1);
88//!
89//!     try {
90//!         $data = $callback();
91//!         $this->set($name, $data, $expire);
92//!     } finally {
93//!         $this->delete($lockName);
94//!     }
95//!
96//!     return $data;
97//! }
98//! ```
99//!
100//! **PHP 源码 bug 复刻**:
101//! 1. 锁 key 无 TTL(若进程崩溃,锁永久存在 → 死锁)
102//! 2. `has()` + `get() !== null` 双查(先 `has` 后 `get`,存在 TOCTOU)
103//!
104//! ### 5. `push` 上限 1000 + array_shift + array_unique(对齐 PHP)
105//!
106//! PHP `think\cache\Driver::push($name, $value)` 第 339-358 行:
107//!
108//! ```php
109//! public function push(string $name, $value, $expire = null)
110//! {
111//!     $data = $this->get($name, []);
112//!     if (!is_array($data)) {
113//!         $data = [];
114//!     }
115//!     $data[] = $value;
116//!
117//!     // 上限 1000
118//!     if (count($data) > 1000) {
119//!         array_shift($data);  // 丢弃最旧
120//!     }
121//!
122//!     // 去重
123//!     $data = array_unique($data);
124//!
125//!     $this->set($name, $data, $expire);
126//!     return $this;
127//! }
128//! ```
129//!
130//! **PHP 行为复刻**:
131//! - 数组上限 1000,超过时丢弃最旧(FIFO)
132//! - `array_unique` 去重(保留首次出现的元素)
133//!
134//! ### 6. `inc` / `dec` 不经序列化(对齐 PHP Redis 驱动)
135//!
136//! PHP `think\cache\driver\Redis::inc($name, $step = 1)` 第 156 行:
137//!
138//! ```php
139//! public function inc(string $name, int $step = 1): bool
140//! {
141//!     if ($this->handler->exists($name)) {
142//!         $value = $this->handler->incrby($name, $step);
143//!         // ...
144//!     }
145//!     // 不存在时初始化为 step
146//!     $this->handler->set($name, $step);
147//!     return true;
148//! }
149//! ```
150//!
151//! Redis 驱动直接使用 `INCRBY` / `DECRBY` 命令,不经过 `serialize`/`unserialize`。
152//! File 驱动则会读取 → 加减 → 写回。本 `MemoryCacheDriver` 采用 File 驱动行为:
153//! 读取 → 解析为 i64 → 加减 → 写回(数字字符串形式)。
154//!
155//! ## 架构
156//!
157//! ```text
158//! SzRustCache (facade)
159//!     ↓
160//! CacheManager (driver manager, like PHP think\Cache extends Manager)
161//!     ↓
162//! CacheDriver trait (like PHP think\cache\Driver abstract)
163//!     ↓
164//! MemoryCacheDriver (PHP think\cache\driver\File analog, in-memory)
165//!     ↓
166//! sz_orm_core::Cache trait / MemoryCache (底层 KV 存储)
167//! ```
168//!
169//! ## 使用示例
170//!
171//! ```ignore
172//! use sz_rust_core::cache::{Cache, MemoryCacheDriver};
173//! use std::time::Duration;
174//!
175//! // 注册默认驱动
176//! let cache = Cache::new();
177//! cache.register_default(MemoryCacheDriver::new());
178//!
179//! // 基本 set/get
180//! cache.set("user:1", "Alice", None).unwrap();
181//! assert_eq!(cache.get::<String>("user:1").unwrap(), Some("Alice".to_string()));
182//!
183//! // is_numeric 短路
184//! cache.set("count", 42i64, None).unwrap();
185//! // PHP bug 复刻:unserialize 返回 string,而非 int
186//! assert_eq!(cache.get::<String>("count").unwrap(), Some("42".to_string()));
187//!
188//! // remember
189//! let val = cache.remember("expensive", None, || 100i64).unwrap();
190//! assert_eq!(val, 100);
191//! ```
192
193use std::collections::HashMap;
194use std::sync::{Arc, OnceLock};
195use std::time::{Duration, Instant};
196
197use parking_lot::{Mutex, RwLock};
198use serde::de::DeserializeOwned;
199use serde::Serialize;
200
201use sz_orm_core::Cache as InnerCache;
202use sz_orm_core::CacheError;
203use sz_orm_core::MemoryCache;
204
205// ============================================================================
206// 全局 Cache facade 实例
207// ============================================================================
208
209/// 全局 `Cache` facade 实例(对齐 PHP `think\facade\Cache` 静态 API)
210///
211/// 使用 `OnceLock` 提供进程级单例,所有 `Cache::default_instance()` 调用
212/// 返回同一个实例。PHP 端通过 `think\facade\Cache::__callStatic` 转发到
213/// `think\App::get('cache')` 容器单例。
214static GLOBAL_CACHE: OnceLock<Cache> = OnceLock::new();
215
216/// 获取全局 `Cache` facade 实例
217///
218/// 对齐 PHP `Cache::set/get/delete/...` 静态调用方式。
219///
220/// ## 注意
221///
222/// 首次调用会创建一个空的 `Cache`(未注册任何驱动)。调用方需先调用
223/// `Cache::init_default` 注册默认驱动后再使用。
224///
225/// ## 示例
226///
227/// ```ignore
228/// use sz_rust_core::cache::{Cache, MemoryCacheDriver};
229///
230/// Cache::init_default(MemoryCacheDriver::new());
231/// Cache::default().set("key", "value", None).unwrap();
232/// ```
233pub fn default_cache() -> &'static Cache {
234    GLOBAL_CACHE.get_or_init(Cache::new)
235}
236
237/// 初始化全局 `Cache` facade 实例(注册默认驱动)
238///
239/// 调用此函数会替换全局 `Cache` 的内部状态。若已注册过默认驱动,会被覆盖。
240///
241/// ## 示例
242///
243/// ```ignore
244/// use sz_rust_core::cache::{default_cache, init_default_cache, MemoryCacheDriver};
245///
246/// init_default_cache(MemoryCacheDriver::new());
247/// default_cache().set("key", "value", None).unwrap();
248/// ```
249pub fn init_default_cache(driver: MemoryCacheDriver) {
250    let cache = default_cache();
251    cache.register_default(driver);
252}
253
254// ============================================================================
255// CacheValue — 缓存值(区分 is_numeric 短路)
256// ============================================================================
257
258/// 缓存值(区分 `is_numeric` 短路与 JSON 序列化)
259///
260/// 对齐 PHP `think\cache\Driver::serialize/unserialize` 行为:
261///
262/// - `Number(s)`:对齐 `is_numeric($data) === true`,存储为字符串
263/// - `Json(s)`:对齐 `serialize($data)`,存储为 JSON 字符串
264///
265/// **PHP bug 复刻**:`unserialize` 对 `is_numeric` 返回 string,而非 int。
266/// 本枚举通过 `Number(String)` 携带原始字符串,反序列化时直接返回 string,
267/// 不还原为 int 类型。
268#[derive(Debug, Clone, PartialEq)]
269pub enum CacheValue {
270    /// 数值型缓存值(对齐 PHP `is_numeric` 短路)
271    ///
272    /// 存储为字符串形式,反序列化时直接返回 string。
273    Number(String),
274    /// JSON 序列化缓存值(对齐 PHP `serialize`)
275    ///
276    /// 存储为 JSON 字符串,反序列化时通过 `serde_json::from_str` 还原。
277    Json(String),
278}
279
280impl CacheValue {
281    /// 序列化缓存值为存储字节
282    ///
283    /// 对齐 PHP `Driver::serialize($data)`:返回字符串后转字节。
284    pub fn to_bytes(&self) -> Vec<u8> {
285        match self {
286            CacheValue::Number(s) => s.as_bytes().to_vec(),
287            CacheValue::Json(s) => s.as_bytes().to_vec(),
288        }
289    }
290
291    /// 从存储字节反序列化缓存值
292    ///
293    /// 对齐 PHP `Driver::unserialize($data)`:
294    /// - 若 `is_numeric` → 返回 `Number(s)`(保留原始字符串)
295    /// - 否则 → 返回 `Json(s)`
296    pub fn from_bytes(bytes: &[u8]) -> Result<CacheValue, CacheError> {
297        let s = std::str::from_utf8(bytes)
298            .map_err(|e| CacheError::DeserializationError(e.to_string()))?;
299        if php_is_numeric(s) {
300            Ok(CacheValue::Number(s.to_string()))
301        } else {
302            Ok(CacheValue::Json(s.to_string()))
303        }
304    }
305
306    /// 是否为数值型(对齐 PHP `is_numeric`)
307    pub fn is_number(&self) -> bool {
308        matches!(self, CacheValue::Number(_))
309    }
310}
311
312// ============================================================================
313// PHP is_numeric 对齐
314// ============================================================================
315
316/// PHP `is_numeric` 简化实现
317///
318/// 对齐 PHP `is_numeric($data)` 行为:
319///
320/// - 整数字符串(如 `"42"`, `"-42"`, `"+42"`)
321/// - 浮点数字符串(如 `"3.14"`, `"-3.14"`, `"+3.14"`)
322/// - 科学计数法(如 `"1e10"`, `"1.5E-3"`)
323///
324/// ## PHP 行为
325///
326/// ```php
327/// is_numeric("42");      // true
328/// is_numeric("-42");     // true
329/// is_numeric("3.14");    // true
330/// is_numeric("1e10");    // true
331/// is_numeric("abc");     // false
332/// is_numeric("12abc");   // false
333/// is_numeric("");        // false
334/// is_numeric("0x1A");    // false(PHP 7+ 不识别十六进制字符串)
335/// ```
336///
337/// ## 限制
338///
339/// PHP `is_numeric` 还支持前导空格(如 `" 42"`),但 think-orm 的
340/// `serialize` 入参 `$data` 是 `$value`(任意类型),不会包含前导空格。
341/// 因此本实现不处理前导空格。
342pub fn php_is_numeric(s: &str) -> bool {
343    if s.is_empty() {
344        return false;
345    }
346    // 整数
347    if s.parse::<i64>().is_ok() {
348        return true;
349    }
350    // 浮点数
351    if s.parse::<f64>().is_ok() {
352        return true;
353    }
354    // 科学计数法(parse::<f64> 已支持 "1e10" 等)
355    // 但 PHP 还允许前导 + 号、前导 - 号等,parse::<f64> 也支持
356    false
357}
358
359// ============================================================================
360// 序列化辅助 — 对齐 PHP think\cache\Driver::serialize
361// ============================================================================
362
363/// 序列化值(对齐 PHP `Driver::serialize($data)`)
364///
365/// PHP `Driver::serialize($data)` 第 612 行:
366/// - `is_numeric($data)` → `(string) $data`
367/// - 否则 → `serialize($data)`(PHP 原生序列化)
368///
369/// Rust 端用 `serde_json::to_string` 替代 PHP `serialize`:
370/// - 整数 / 浮点数 → `CacheValue::Number(s)`
371/// - 其他 → `CacheValue::Json(s)`
372pub fn php_serialize<T: Serialize>(value: &T) -> Result<CacheValue, CacheError> {
373    // 短路:字符串字面量可能是数字字符串
374    // 对齐 PHP: $data = "42"; is_numeric($data) === true
375    let json =
376        serde_json::to_string(value).map_err(|e| CacheError::SerializationError(e.to_string()))?;
377
378    // serde_json 序列化 string "42" → "\"42\""(带引号)
379    // serde_json 序列化 i64 42 → "42"(无引号)
380    // 因此 JSON 字符串无引号即为 is_numeric
381    if php_is_numeric(&json) {
382        Ok(CacheValue::Number(json))
383    } else {
384        Ok(CacheValue::Json(json))
385    }
386}
387
388/// 反序列化值(对齐 PHP `Driver::unserialize($data)`)
389///
390/// PHP `Driver::unserialize($data)` 第 623 行:
391/// - `is_numeric($data)` → 返回 string(⚠️ PHP 源码 bug:不还原为 int)
392/// - 否则 → `unserialize($data)`
393///
394/// ## 泛型
395///
396/// - `T = String`:对齐 PHP `unserialize` 对 numeric 返回 string 的行为
397/// - `T = Other`:使用 `serde_json::from_str` 还原
398///
399/// **注意**:若想获取 `i64`,需调用方自行 `.parse::<i64>()`,
400/// 对齐 PHP 业务代码中 `(int) Cache::get('count')` 的强转模式。
401pub fn php_unserialize<T: DeserializeOwned>(value: &CacheValue) -> Result<Option<T>, CacheError> {
402    match value {
403        CacheValue::Number(s) => {
404            // PHP bug 复刻:numeric 值返回 string
405            // 若 T 是 String,直接返回;否则尝试解析
406            serde_json::from_str::<T>(&format!("\"{}\"", s))
407                .map(Some)
408                .map_err(|e| CacheError::DeserializationError(e.to_string()))
409        }
410        CacheValue::Json(s) => serde_json::from_str::<T>(s)
411            .map(Some)
412            .map_err(|e| CacheError::DeserializationError(e.to_string())),
413    }
414}
415
416// ============================================================================
417// CacheDriver trait — 对齐 PHP think\cache\Driver
418// ============================================================================
419
420/// 缓存驱动 trait(对齐 PHP `think\cache\Driver` 抽象基类)
421///
422/// PHP `think\cache\Driver`(359 行)定义了缓存驱动的核心 API:
423/// `get/set/delete/has/inc/dec/remember/pull/push/tag/clear`。
424///
425/// 本 trait 提供等价的 Rust 抽象,底层由具体驱动(如 `MemoryCacheDriver`)
426/// 实现,上层 `Cache` facade 委托到 trait 方法。
427///
428/// ## 与 `sz_orm_core::Cache` 的关系
429///
430/// `sz_orm_core::Cache` trait 提供底层 KV 操作(`get/set/delete/exists`),
431/// 本 trait 在其之上扩展 PHP think-orm 行为:
432///
433/// - `inc/dec`:自增/自减(不经序列化层)
434/// - `has`:键是否存在(对齐 PHP `has`,含 TTL 过期检查)
435/// - `clear`:清空所有缓存
436pub trait CacheDriver: Send + Sync {
437    /// 读取缓存原始字节
438    fn get_raw(&self, key: &str) -> Result<Option<Vec<u8>>, CacheError>;
439
440    /// 写入缓存原始字节
441    fn set_raw(&self, key: &str, value: Vec<u8>, ttl: Option<Duration>) -> Result<(), CacheError>;
442
443    /// 删除缓存
444    fn delete(&self, key: &str) -> Result<(), CacheError>;
445
446    /// 判断键是否存在(对齐 PHP `has`,含 TTL 过期检查)
447    fn has(&self, key: &str) -> Result<bool, CacheError>;
448
449    /// 自增(对齐 PHP `inc`,不经序列化层)
450    ///
451    /// PHP Redis 驱动直接 `INCRBY`;File 驱动读取 → 加减 → 写回。
452    /// 本 trait 默认实现采用 File 驱动行为。
453    ///
454    /// ## 行为
455    ///
456    /// - 键不存在:初始化为 `step`,返回 `step`
457    /// - 键存在:解析为 i64 → 加 `step` → 写回 → 返回新值
458    /// - 解析失败:返回 `CacheError`
459    fn inc(&self, key: &str, step: i64) -> Result<i64, CacheError> {
460        let current = match self.get_raw(key)? {
461            Some(bytes) => {
462                let s = std::str::from_utf8(&bytes)
463                    .map_err(|e| CacheError::DeserializationError(e.to_string()))?;
464                s.parse::<i64>().map_err(|e| {
465                    CacheError::DeserializationError(format!("inc: parse {} failed: {}", s, e))
466                })?
467            }
468            None => 0,
469        };
470        let new_value = current + step;
471        self.set_raw(key, new_value.to_string().into_bytes(), None)?;
472        Ok(new_value)
473    }
474
475    /// 自减(对齐 PHP `dec`,不经序列化层)
476    ///
477    /// 默认实现委托到 `inc(key, -step)`。
478    fn dec(&self, key: &str, step: i64) -> Result<i64, CacheError> {
479        self.inc(key, -step)
480    }
481
482    /// 清空所有缓存(对齐 PHP `clear`)
483    fn clear(&self) -> Result<(), CacheError>;
484
485    // ========================================================================
486    // 缓存标签(对齐 PHP think\cache\Driver tag 相关方法)
487    // ========================================================================
488
489    /// 构造缓存 key(对齐 PHP `Driver::getCacheKey`)
490    ///
491    /// PHP `Driver::getCacheKey(name)` 第 86-89 行:
492    /// ```php
493    /// return $this->options['prefix'] . $name;
494    /// ```
495    ///
496    /// 默认实现:无前缀(对齐 `MemoryCacheDriver` / `MultiLevelCacheDriver`)。
497    /// `RedisCacheDriver` 重写为 `prefix + name`。
498    fn get_cache_key(&self, name: &str) -> String {
499        name.to_string()
500    }
501
502    /// 构造 tag key(对齐 PHP `Driver::getTagKey`)
503    ///
504    /// PHP `Driver::getTagKey(tag)` 第 226-229 行:
505    /// ```php
506    /// return $this->options['tag_prefix'] . md5($tag);
507    /// ```
508    ///
509    /// 默认实现:`format!("tag:{}", compute_md5(tag))`(PHP 默认 `tag_prefix = "tag:"`)。
510    fn get_tag_key(&self, tag: &str) -> String {
511        format!("tag:{}", compute_md5(tag))
512    }
513
514    /// 追加 cache_key 到标签集合(对齐 PHP `Driver::append` / `Driver::push`)
515    ///
516    /// PHP `Driver::append(name, value)` 调用 `push(name, value)`(第 140-143 行),
517    /// `push` 实现(第 114-131 行):
518    ///
519    /// ```php
520    /// public function push(string $name, $value): void
521    /// {
522    ///     $item = $this->get($name, []);
523    ///     if (!is_array($item)) {
524    ///         throw new InvalidArgumentException('only array cache can be push');
525    ///     }
526    ///     $item[] = $value;
527    ///     if (count($item) > 1000) {
528    ///         array_shift($item);
529    ///     }
530    ///     $item = array_unique($item);
531    ///     $this->set($name, $item);
532    /// }
533    /// ```
534    ///
535    /// ## 参数
536    ///
537    /// - `tag_key`:标签 key(`getTagKey(tag)` 返回值,**未**应用 `getCacheKey` 前缀)
538    /// - `cache_key`:缓存 key(`getCacheKey(name)` 返回值,**已**应用前缀)
539    ///
540    /// ## 行为
541    ///
542    /// 默认实现采用 File 驱动语义(`push`):
543    /// 1. 读取 `getCacheKey(tag_key)` → 反序列化为 `Vec<String>`
544    /// 2. 追加 `cache_key`
545    /// 3. 长度 > 1000 → 丢弃最旧(FIFO,对齐 `array_shift`)
546    /// 4. 去重(对齐 `array_unique`,保留首次出现)
547    /// 5. 写回 `getCacheKey(tag_key)`
548    ///
549    /// `RedisCacheDriver` 重写为 `sAdd`(Redis Set 语义)。
550    fn tag_append(&self, tag_key: &str, cache_key: &str) -> Result<(), CacheError> {
551        let storage_key = self.get_cache_key(tag_key);
552        // 对齐 PHP: $item = $this->get($name, []);
553        let mut items: Vec<String> = match self.get_raw(&storage_key)? {
554            Some(bytes) => serde_json::from_slice(&bytes)
555                .map_err(|e| CacheError::DeserializationError(format!("tag_append: {}", e)))?,
556            None => Vec::new(),
557        };
558        // 对齐 PHP: $item[] = $value;
559        items.push(cache_key.to_string());
560        // 对齐 PHP: if (count($item) > 1000) { array_shift($item); }
561        while items.len() > 1000 {
562            items.remove(0);
563        }
564        // 对齐 PHP: $item = array_unique($item);
565        let mut seen = HashSet::new();
566        items.retain(|item| seen.insert(item.clone()));
567        // 对齐 PHP: $this->set($name, $item);
568        let serialized = serde_json::to_vec(&items)
569            .map_err(|e| CacheError::SerializationError(e.to_string()))?;
570        self.set_raw(&storage_key, serialized, None)
571    }
572
573    /// 获取标签包含的所有缓存 key(对齐 PHP `Driver::getTagItems`)
574    ///
575    /// PHP `Driver::getTagItems(tag)` 第 214-218 行:
576    /// ```php
577    /// public function getTagItems(string $tag): array
578    /// {
579    ///     $name = $this->getTagKey($tag);
580    ///     return $this->get($name, []);
581    /// }
582    /// ```
583    ///
584    /// ## 参数
585    ///
586    /// - `tag`:标签名(方法内部计算 `getTagKey` + 应用 `getCacheKey` 前缀)
587    ///
588    /// ## 返回
589    ///
590    /// 返回该标签下所有缓存 key(已应用前缀)的列表。
591    fn tag_items(&self, tag: &str) -> Result<Vec<String>, CacheError> {
592        let tag_key = self.get_tag_key(tag);
593        let storage_key = self.get_cache_key(&tag_key);
594        match self.get_raw(&storage_key)? {
595            Some(bytes) => {
596                let items: Vec<String> = serde_json::from_slice(&bytes)
597                    .map_err(|e| CacheError::DeserializationError(format!("tag_items: {}", e)))?;
598                Ok(items)
599            }
600            None => Ok(Vec::new()),
601        }
602    }
603
604    /// 批量删除缓存 key(对齐 PHP `Redis::clearTag`)
605    ///
606    /// PHP `Redis::clearTag(keys)` 第 217-221 行:
607    /// ```php
608    /// public function clearTag(array $keys): void
609    /// {
610    ///     $this->handler->del($keys);
611    /// }
612    /// ```
613    ///
614    /// ## 注意
615    ///
616    /// `keys` 是**已应用前缀**的缓存 key(来自 `tag_items` 返回值),
617    /// 因此本方法**不得**再次应用 `getCacheKey`。
618    ///
619    /// 默认实现:对每个 key 调用 `delete`(适用于无前缀驱动)。
620    /// `RedisCacheDriver` 重写为 `del_many`(raw delete,不应用前缀)。
621    fn tag_clear(&self, keys: &[String]) -> Result<(), CacheError> {
622        for key in keys {
623            let _ = self.delete(key);
624        }
625        Ok(())
626    }
627}
628
629// ============================================================================
630// MemoryCacheDriver — 内存驱动(对齐 PHP think\cache\driver\File)
631// ============================================================================
632
633/// 内存缓存驱动(对齐 PHP `think\cache\driver\File`)
634///
635/// 基于 `sz_orm_core::MemoryCache`,提供进程内内存缓存。
636///
637/// ## PHP 对齐
638///
639/// PHP `think\cache\driver\File` 使用文件系统存储缓存,序列化为 PHP 字符串
640/// 加 `<?php exit();?>` 头部防护。本驱动使用内存 HashMap,简化文件 IO,
641/// 但保留 PHP think-orm 的核心行为:
642///
643/// - `get`:TTL 过期返回 `None`
644/// - `set`:支持 TTL
645/// - `has`:TTL 过期返回 `false`
646/// - `inc/dec`:读取 → 加减 → 写回(数字字符串)
647pub struct MemoryCacheDriver {
648    inner: MemoryCache,
649}
650
651impl MemoryCacheDriver {
652    /// 创建新的内存缓存驱动
653    pub fn new() -> Self {
654        Self {
655            inner: MemoryCache::new(),
656        }
657    }
658
659    /// 创建带默认 TTL 的内存缓存驱动
660    pub fn with_default_ttl(ttl: Duration) -> Self {
661        Self {
662            inner: MemoryCache::with_ttl(ttl),
663        }
664    }
665}
666
667impl Default for MemoryCacheDriver {
668    fn default() -> Self {
669        Self::new()
670    }
671}
672
673impl CacheDriver for MemoryCacheDriver {
674    fn get_raw(&self, key: &str) -> Result<Option<Vec<u8>>, CacheError> {
675        InnerCache::get(&self.inner, key)
676    }
677
678    fn set_raw(&self, key: &str, value: Vec<u8>, ttl: Option<Duration>) -> Result<(), CacheError> {
679        InnerCache::set(&self.inner, key, value, ttl)
680    }
681
682    fn delete(&self, key: &str) -> Result<(), CacheError> {
683        InnerCache::delete(&self.inner, key)
684    }
685
686    fn has(&self, key: &str) -> Result<bool, CacheError> {
687        InnerCache::exists(&self.inner, key)
688    }
689
690    fn clear(&self) -> Result<(), CacheError> {
691        InnerCache::clear(&self.inner)
692    }
693}
694
695// ============================================================================
696// CacheManager — 驱动管理器(对齐 PHP think\Cache extends Manager)
697// ============================================================================
698
699/// 缓存驱动管理器(对齐 PHP `think\Cache extends Manager`)
700///
701/// PHP `think\Cache` 继承 `think\Manager`,提供多驱动支持:
702///
703/// ```php
704/// $cache = new think\Cache();
705/// $cache->store('file')->set('key', 'value');
706/// $cache->store('redis')->set('key', 'value');
707/// ```
708///
709/// 本结构体提供等价的 Rust 抽象:
710///
711/// - `register_store(name, driver)`:注册命名驱动
712/// - `store(name)`:获取命名驱动
713/// - `default_store()`:获取默认驱动
714pub struct CacheManager {
715    /// 默认驱动名(对齐 PHP `'default' => Env::get('cache.driver', 'redis')`)
716    default: String,
717    /// 命名驱动表(对齐 PHP `Manager::$drivers`)
718    stores: HashMap<String, Box<dyn CacheDriver>>,
719}
720
721impl CacheManager {
722    /// 创建新的驱动管理器(无默认驱动)
723    pub fn new() -> Self {
724        Self {
725            default: String::new(),
726            stores: HashMap::new(),
727        }
728    }
729
730    /// 注册命名驱动
731    ///
732    /// 对齐 PHP `Manager::createDriver(array $config)` + `$this->drivers[$name] = $driver`。
733    ///
734    /// ## 参数
735    ///
736    /// - `name`:驱动名(如 `"file"`、`"redis"`)
737    /// - `driver`:驱动实例
738    pub fn register_store(&mut self, name: impl Into<String>, driver: Box<dyn CacheDriver>) {
739        let name = name.into();
740        if self.default.is_empty() {
741            self.default = name.clone();
742        }
743        self.stores.insert(name, driver);
744    }
745
746    /// 设置默认驱动名
747    ///
748    /// 对齐 PHP `config/cache.php` 中 `'default' => 'redis'`。
749    pub fn set_default(&mut self, name: impl Into<String>) -> Result<(), CacheError> {
750        let name = name.into();
751        if !self.stores.contains_key(&name) {
752            return Err(CacheError::NotFound(format!(
753                "cache store '{}' not registered",
754                name
755            )));
756        }
757        self.default = name;
758        Ok(())
759    }
760
761    /// 获取命名驱动
762    ///
763    /// 对齐 PHP `Manager::store(string $name = null)`。
764    pub fn store(&self, name: &str) -> Result<&dyn CacheDriver, CacheError> {
765        self.stores
766            .get(name)
767            .map(|d| d.as_ref())
768            .ok_or_else(|| CacheError::NotFound(format!("cache store '{}' not found", name)))
769    }
770
771    /// 获取默认驱动
772    ///
773    /// 对齐 PHP `$cache->store()`(默认驱动)。
774    pub fn default_store(&self) -> Result<&dyn CacheDriver, CacheError> {
775        if self.default.is_empty() {
776            return Err(CacheError::NotFound(
777                "no default cache store registered".to_string(),
778            ));
779        }
780        self.store(&self.default)
781    }
782}
783
784impl Default for CacheManager {
785    fn default() -> Self {
786        Self::new()
787    }
788}
789
790// ============================================================================
791// Cache facade — 对齐 PHP think\facade\Cache
792// ============================================================================
793
794/// Cache facade(对齐 PHP `think\facade\Cache`)
795///
796/// 通过全局单例 + 委托 `CacheManager` 提供 PHP facade 风格 API。
797///
798/// ## 使用方式
799///
800/// ### 1. 全局使用(对齐 PHP `Cache::set(...)` 静态调用)
801///
802/// ```ignore
803/// use sz_rust_core::cache::{init_default_cache, default_cache, MemoryCacheDriver};
804///
805/// init_default_cache(MemoryCacheDriver::new());
806/// default_cache().set("key", "value", None).unwrap();
807/// ```
808///
809/// ### 2. 独立实例(用于测试隔离)
810///
811/// ```ignore
812/// use sz_rust_core::cache::{Cache, MemoryCacheDriver};
813///
814/// let cache = Cache::new();
815/// cache.register_default(MemoryCacheDriver::new());
816/// cache.set("key", "value", None).unwrap();
817/// ```
818pub struct Cache {
819    manager: RwLock<CacheManager>,
820    /// remember 锁等待参数(对齐 PHP 200ms 轮询 + 5s 超时)
821    remember_lock_poll_interval: Duration,
822    remember_lock_timeout: Duration,
823    /// singleflight inflight map(按 key 互斥,防止缓存击穿)
824    /// Rust 特有扩展:用 `parking_lot::Mutex` 实现真正的互斥,对齐 PHP `remember` 的"锁意图"但用正确方式实现
825    inflight: Mutex<HashMap<String, Arc<Mutex<()>>>>,
826}
827
828impl Cache {
829    /// 创建空的 Cache facade 实例
830    pub fn new() -> Self {
831        Self {
832            manager: RwLock::new(CacheManager::new()),
833            remember_lock_poll_interval: Duration::from_millis(200),
834            remember_lock_timeout: Duration::from_secs(5),
835            inflight: Mutex::new(HashMap::new()),
836        }
837    }
838
839    /// 注册默认驱动
840    ///
841    /// 等价于 PHP `think\App::get('cache')` + 注册默认 store。
842    pub fn register_default(&self, driver: MemoryCacheDriver) {
843        let mut mgr = self.manager.write();
844        mgr.register_store("default", Box::new(driver));
845    }
846
847    /// 注册命名驱动
848    pub fn register_store(&self, name: impl Into<String>, driver: Box<dyn CacheDriver>) {
849        let mut mgr = self.manager.write();
850        mgr.register_store(name, driver);
851    }
852
853    /// 设置默认驱动名
854    pub fn set_default_store(&self, name: impl Into<String>) -> Result<(), CacheError> {
855        let mut mgr = self.manager.write();
856        mgr.set_default(name)
857    }
858
859    // ========================================================================
860    // PHP think\facade\Cache 核心 API
861    // ========================================================================
862
863    /// 写入缓存(对齐 PHP `Cache::set($name, $value, $ttl = null)`)
864    ///
865    /// PHP `Driver::set($name, $value, $ttl = null)` 第 110 行:
866    ///
867    /// ```php
868    /// public function set($name, $value, $expire = null): bool
869    /// {
870    ///     $this->writeTimes++;
871    ///     if (is_null($expire)) {
872    ///         $expire = $this->options['expire'];
873    ///     }
874    ///     $data = $this->serialize($value);
875    ///     // ... 写入底层存储
876    /// }
877    /// ```
878    ///
879    /// ## 参数
880    ///
881    /// - `key`:缓存键
882    /// - `value`:缓存值(实现 `Serialize`)
883    /// - `ttl`:过期时间(`None` 永不过期,对齐 PHP `$expire = null`)
884    #[tracing::instrument(skip(self, value))]
885    pub fn set<T: Serialize>(
886        &self,
887        key: &str,
888        value: T,
889        ttl: Option<Duration>,
890    ) -> Result<(), CacheError> {
891        let cache_value = php_serialize(&value)?;
892        let bytes = cache_value.to_bytes();
893        let mgr = self.manager.read();
894        let driver = mgr.default_store()?;
895        driver.set_raw(key, bytes, ttl)
896    }
897
898    /// 读取缓存(对齐 PHP `Cache::get($name, $default = null)`)
899    ///
900    /// PHP `Driver::get($name, $default = null)` 第 90 行:
901    ///
902    /// ```php
903    /// public function get($name, $default = null)
904    /// {
905    ///     $this->readTimes++;
906    ///     $value = $this->read($name);  // 读取原始字节
907    ///     if (is_null($value)) {
908    ///         return $default;
909    ///     }
910    ///     return $this->unserialize($value);  // ⚠️ numeric 返回 string
911    /// }
912    /// ```
913    ///
914    /// ## 泛型
915    ///
916    /// - `T = String`:对齐 PHP `unserialize` 对 numeric 返回 string 的行为
917    /// - `T = Other`:通过 `serde_json::from_str` 还原
918    ///
919    /// ## PHP bug 复刻
920    ///
921    /// PHP `unserialize` 对 `is_numeric` 的值返回 string,而非 int。
922    /// 调用方若想获取 `i64`,需自行 `.parse::<i64>()`,对齐 PHP 业务代码
923    /// `(int) Cache::get('count')` 的强转模式。
924    ///
925    /// ## 参数
926    ///
927    /// - `key`:缓存键
928    ///
929    /// ## 返回
930    ///
931    /// - `Ok(Some(value))`:缓存命中
932    /// - `Ok(None)`:缓存未命中或已过期
933    #[tracing::instrument(skip(self))]
934    pub fn get<T: DeserializeOwned>(&self, key: &str) -> Result<Option<T>, CacheError> {
935        let mgr = self.manager.read();
936        let driver = mgr.default_store()?;
937        match driver.get_raw(key)? {
938            None => Ok(None),
939            Some(bytes) => {
940                let cache_value = CacheValue::from_bytes(&bytes)?;
941                php_unserialize(&cache_value)
942            }
943        }
944    }
945
946    /// 读取缓存,未命中时返回默认值(对齐 PHP `Cache::get($name, $default)`)
947    pub fn get_or<T: DeserializeOwned>(&self, key: &str, default: T) -> Result<T, CacheError> {
948        match self.get::<T>(key)? {
949            Some(v) => Ok(v),
950            None => Ok(default),
951        }
952    }
953
954    /// remember 专用的弱类型读取(对齐 PHP 弱类型强转)
955    ///
956    /// PHP 是弱类型语言,`remember` 返回 `unserialize($data)` 后的值。
957    /// 当存储的是 numeric 时,PHP `unserialize` 返回 string(源码 bug),
958    /// 但调用方通常期望得到原始类型(如 int),PHP 通过隐式强转实现。
959    ///
960    /// Rust 端 `remember<T>` 是泛型,需要能从 string 还原为 T:
961    /// 1. 先尝试 `get::<T>` 直接反序列化
962    /// 2. 失败时降级 `get::<String>` + `serde_json::from_str::<T>(&s)`
963    ///    (对齐 PHP `(int) Cache::get('count')` 强转模式)
964    ///
965    /// ## 示例
966    ///
967    /// - 存储 `i64 42` → `CacheValue::Number("42")`
968    /// - `get::<i64>` 失败(JSON string 不是 number)
969    /// - 降级 `get::<String>` 返回 `"42"`
970    /// - `serde_json::from_str::<i64>("42")` 成功返回 `42`("42" 是合法 JSON number)
971    fn get_weak<T: DeserializeOwned>(&self, key: &str) -> Result<Option<T>, CacheError> {
972        match self.get::<T>(key) {
973            Ok(v) => Ok(v),
974            Err(CacheError::DeserializationError(_)) => {
975                // 降级:尝试从 string 还原为 T
976                // 对齐 PHP: numeric 存储返回 string,调用方需自行强转
977                match self.get::<String>(key) {
978                    Ok(Some(s)) => serde_json::from_str::<T>(&s)
979                        .map(Some)
980                        .map_err(|e| CacheError::DeserializationError(e.to_string())),
981                    Ok(None) => Ok(None),
982                    Err(e) => Err(e),
983                }
984            }
985            Err(e) => Err(e),
986        }
987    }
988
989    /// 删除缓存(对齐 PHP `Cache::delete($name)`)
990    #[tracing::instrument(skip(self))]
991    pub fn delete(&self, key: &str) -> Result<(), CacheError> {
992        let mgr = self.manager.read();
993        let driver = mgr.default_store()?;
994        driver.delete(key)
995    }
996
997    /// 判断键是否存在(对齐 PHP `Cache::has($name)`)
998    ///
999    /// PHP `Driver::has($name)` 第 222 行:
1000    ///
1001    /// ```php
1002    /// public function has($name): bool
1003    /// {
1004    ///     return $this->read($name) !== null;
1005    /// }
1006    /// ```
1007    ///
1008    /// ## 注意
1009    ///
1010    /// PHP `has` 通过 `read` 检查是否为 null,会同时检查 TTL 过期。
1011    pub fn has(&self, key: &str) -> Result<bool, CacheError> {
1012        let mgr = self.manager.read();
1013        let driver = mgr.default_store()?;
1014        driver.has(key)
1015    }
1016
1017    /// 自增(对齐 PHP `Cache::inc($name, $step = 1)`)
1018    ///
1019    /// PHP Redis 驱动直接 `INCRBY`;File 驱动读取 → 加减 → 写回。
1020    /// 本驱动默认实现采用 File 驱动行为。
1021    ///
1022    /// ## 行为
1023    ///
1024    /// - 键不存在:初始化为 `step`
1025    /// - 键存在:解析为 i64 → 加 `step` → 写回
1026    pub fn inc(&self, key: &str, step: i64) -> Result<i64, CacheError> {
1027        let mgr = self.manager.read();
1028        let driver = mgr.default_store()?;
1029        driver.inc(key, step)
1030    }
1031
1032    /// 自减(对齐 PHP `Cache::dec($name, $step = 1)`)
1033    pub fn dec(&self, key: &str, step: i64) -> Result<i64, CacheError> {
1034        let mgr = self.manager.read();
1035        let driver = mgr.default_store()?;
1036        driver.dec(key, step)
1037    }
1038
1039    /// 自增 1(便捷方法,对齐 PHP `Cache::inc($name)` 默认参数)
1040    pub fn increment(&self, key: &str) -> Result<i64, CacheError> {
1041        self.inc(key, 1)
1042    }
1043
1044    /// 自减 1(便捷方法,对齐 PHP `Cache::dec($name)` 默认参数)
1045    pub fn decrement(&self, key: &str) -> Result<i64, CacheError> {
1046        self.dec(key, 1)
1047    }
1048
1049    /// 读取并删除(对齐 PHP `Cache::pull($name, $default = null)`)
1050    ///
1051    /// PHP `Driver::pull($name, $default = null)` 第 332 行:
1052    ///
1053    /// ```php
1054    /// public function pull(string $name, $default = null)
1055    /// {
1056    ///     $result = $this->get($name, $default);
1057    ///     $this->delete($name);
1058    ///     return $result;
1059    /// }
1060    /// ```
1061    pub fn pull<T: DeserializeOwned>(&self, key: &str) -> Result<Option<T>, CacheError> {
1062        let value = self.get::<T>(key)?;
1063        if value.is_some() {
1064            self.delete(key)?;
1065        }
1066        Ok(value)
1067    }
1068
1069    /// 追加到数组缓存(对齐 PHP `Cache::push($name, $value, $expire = null)`)
1070    ///
1071    /// PHP `Driver::push($name, $value, $expire = null)` 第 339-358 行:
1072    ///
1073    /// ```php
1074    /// public function push(string $name, $value, $expire = null)
1075    /// {
1076    ///     $data = $this->get($name, []);
1077    ///     if (!is_array($data)) {
1078    ///         $data = [];
1079    ///     }
1080    ///     $data[] = $value;
1081    ///     if (count($data) > 1000) {
1082    ///         array_shift($data);
1083    ///     }
1084    ///     $data = array_unique($data);
1085    ///     $this->set($name, $data, $expire);
1086    ///     return $this;
1087    /// }
1088    /// ```
1089    ///
1090    /// ## 行为
1091    ///
1092    /// - 缓存不存在 → 创建 `vec![value]`
1093    /// - 缓存非数组 → 创建 `vec![value]`
1094    /// - 缓存为数组 → 追加 `value`
1095    /// - 长度 > 1000 → 丢弃最旧(FIFO)
1096    /// - `array_unique` 去重(保留首次出现的元素)
1097    pub fn push<T: Serialize + DeserializeOwned + PartialEq + Clone>(
1098        &self,
1099        key: &str,
1100        value: T,
1101        ttl: Option<Duration>,
1102    ) -> Result<(), CacheError> {
1103        // 对齐 PHP: $data = $this->get($name, []);
1104        // PHP is_array($data) 为 false 时(含反序列化失败),重置为 []
1105        let mut data: Vec<T> = match self.get::<Vec<T>>(key) {
1106            Ok(Some(v)) => v,
1107            Ok(None) => Vec::new(),
1108            Err(_) => Vec::new(),
1109        };
1110        data.push(value);
1111
1112        // 对齐 PHP array_shift:长度 > 1000 时丢弃最旧
1113        while data.len() > 1000 {
1114            data.remove(0);
1115        }
1116
1117        // 对齐 PHP array_unique:去重(保留首次出现的元素)
1118        let mut seen = std::collections::HashSet::new();
1119        data.retain(|item| seen.insert(item.hashable_string()));
1120
1121        self.set(key, data, ttl)
1122    }
1123
1124    /// 缓存击穿防护读取(对齐 PHP `Cache::remember($name, callable, $expire = null)`)
1125    ///
1126    /// PHP `Driver::remember` 第 287-310 行 + PHP bug 复刻:
1127    ///
1128    /// 1. 先 `get($name)`,命中直接返回
1129    /// 2. 抢锁 `set($name . '_lock', 1)`(无 TTL,PHP 源码 bug)
1130    /// 3. 等待锁释放,200ms 轮询,5 秒超时
1131    /// 4. 锁释放后 `get($name)`,命中则返回
1132    /// 5. 超时仍未释放:直接调用 `callback()`(防止永久阻塞)
1133    /// 6. 抢到锁:调用 `callback()` → `set($name, $data, $expire)` → 释放锁
1134    ///
1135    /// ## PHP bug 复刻
1136    ///
1137    /// 1. **锁 key 无 TTL**:若进程崩溃,锁永久存在 → 死锁
1138    /// 2. **`has()` + `get()` 双查 TOCTOU**:先 `has` 后 `get`
1139    ///
1140    /// ## ⚠ 异步上下文警告
1141    ///
1142    /// 本方法在等待锁释放时使用 `std::thread::sleep`,会**阻塞 tokio worker 线程**。
1143    /// 在异步上下文(axum handler / tokio task)中应改用 [`Cache::remember_async`],
1144    /// 后者使用 `tokio::time::sleep` 让出 worker,避免阻塞调度器。
1145    ///
1146    /// ## 参数
1147    ///
1148    /// - `key`:缓存键
1149    /// - `ttl`:缓存过期时间
1150    /// - `callback`:未命中时的回调函数
1151    #[tracing::instrument(skip(self, callback))]
1152    pub fn remember<T, F>(
1153        &self,
1154        key: &str,
1155        ttl: Option<Duration>,
1156        callback: F,
1157    ) -> Result<T, CacheError>
1158    where
1159        T: Serialize + DeserializeOwned,
1160        F: FnOnce() -> T,
1161    {
1162        // 1. 先尝试读取缓存(弱类型读取,对齐 PHP 弱类型强转)
1163        if let Some(cached) = self.get_weak::<T>(key)? {
1164            return Ok(cached);
1165        }
1166
1167        // 2. 抢锁
1168        let lock_key = format!("{}_lock", key);
1169
1170        // PHP 源码 bug 复刻:先 has() 后 get() 双查
1171        if self.has(&lock_key)? {
1172            // 等待锁释放,200ms 轮询,5s 超时
1173            let start = Instant::now();
1174            while self.has(&lock_key)? {
1175                if start.elapsed() >= self.remember_lock_timeout {
1176                    // 超时仍未释放,直接调用 callback(防止永久阻塞)
1177                    return Ok(callback());
1178                }
1179                std::thread::sleep(self.remember_lock_poll_interval);
1180            }
1181
1182            // 锁释放后再次读取(弱类型读取)
1183            if let Some(cached) = self.get_weak::<T>(key)? {
1184                return Ok(cached);
1185            }
1186        }
1187
1188        // 抢到锁(无 TTL,PHP 源码 bug)
1189        self.set(&lock_key, 1i64, None)?;
1190
1191        // 调用 callback 并写入缓存
1192        let result = callback();
1193        let _ = self.set(key, &result, ttl);
1194
1195        // 释放锁
1196        let _ = self.delete(&lock_key);
1197
1198        Ok(result)
1199    }
1200
1201    /// 缓存击穿防护读取(异步版本,对齐 PHP `Cache::remember` 的 async 实现)
1202    ///
1203    /// 与 [`Cache::remember`] 行为一致,但使用 `tokio::time::sleep` 替代
1204    /// `std::thread::sleep`,避免在异步上下文中阻塞 tokio worker 线程。
1205    /// 同时支持异步 callback,避免在 callback 中执行阻塞 IO 时阻塞 worker。
1206    ///
1207    /// ## 与同步版本的差异
1208    ///
1209    /// | 维度 | `remember` | `remember_async` |
1210    /// |------|-----------|------------------|
1211    /// | 等待锁释放 | `std::thread::sleep`(阻塞 worker) | `tokio::time::sleep`(让出 worker) |
1212    /// | callback 类型 | `FnOnce() -> T` | `async fn -> T` |
1213    /// | 适用场景 | 同步上下文 / 短时计算 | 异步上下文 / IO 密集型回源 |
1214    ///
1215    /// ## 参数
1216    ///
1217    /// - `key`:缓存键
1218    /// - `ttl`:缓存过期时间
1219    /// - `callback`:未命中时的异步回调函数
1220    ///
1221    /// ## 用法
1222    ///
1223    /// ```ignore
1224    /// # async fn example(cache: &sz_rust_core::cache::Cache) {
1225    /// let user: User = cache.remember_async("user_1", Some(Duration::from_secs(60)), || async {
1226    ///     // 异步回源逻辑(如 DB 查询)
1227    ///     User::find_async(1).await
1228    /// }).await?;
1229    /// # }
1230    /// ```
1231    pub async fn remember_async<T, F, Fut>(
1232        &self,
1233        key: &str,
1234        ttl: Option<Duration>,
1235        callback: F,
1236    ) -> Result<T, CacheError>
1237    where
1238        T: Serialize + DeserializeOwned + Clone,
1239        F: FnOnce() -> Fut,
1240        Fut: std::future::Future<Output = T>,
1241    {
1242        // 1. 先尝试读取缓存(弱类型读取,对齐 PHP 弱类型强转)
1243        if let Some(cached) = self.get_weak::<T>(key)? {
1244            return Ok(cached);
1245        }
1246
1247        // 2. 抢锁
1248        let lock_key = format!("{}_lock", key);
1249
1250        // PHP 源码 bug 复刻:先 has() 后 get() 双查
1251        if self.has(&lock_key)? {
1252            // 等待锁释放,200ms 轮询,5s 超时(异步等待,不阻塞 worker)
1253            let start = Instant::now();
1254            while self.has(&lock_key)? {
1255                if start.elapsed() >= self.remember_lock_timeout {
1256                    // 超时仍未释放,直接调用 callback(防止永久阻塞)
1257                    let result = callback().await;
1258                    let _ = self.set(key, &result, ttl);
1259                    return Ok(result);
1260                }
1261                tokio::time::sleep(self.remember_lock_poll_interval).await;
1262            }
1263
1264            // 锁释放后再次读取(弱类型读取)
1265            if let Some(cached) = self.get_weak::<T>(key)? {
1266                return Ok(cached);
1267            }
1268        }
1269
1270        // 抢到锁(无 TTL,PHP 源码 bug)
1271        self.set(&lock_key, 1i64, None)?;
1272
1273        // 调用异步 callback 并写入缓存
1274        let result = callback().await;
1275        let _ = self.set(key, &result, ttl);
1276
1277        // 释放锁
1278        let _ = self.delete(&lock_key);
1279
1280        Ok(result)
1281    }
1282
1283    /// 清空所有缓存(对齐 PHP `Cache::clear()`)
1284    #[tracing::instrument(skip(self))]
1285    pub fn clear(&self) -> Result<(), CacheError> {
1286        let mgr = self.manager.read();
1287        let driver = mgr.default_store()?;
1288        driver.clear()
1289    }
1290
1291    // ========================================================================
1292    // 缓存失效策略(对齐 PHP 业务代码写后失效模式)
1293    // ========================================================================
1294
1295    /// 批量删除多个缓存 key(对齐 PHP `Driver::deleteMultiple($keys): bool`)
1296    ///
1297    /// PHP `think\cache\Driver::deleteMultiple` 第 342-351 行:
1298    /// ```php
1299    /// public function deleteMultiple($keys): bool
1300    /// {
1301    ///     foreach ($keys as $key) {
1302    ///         $result = $this->delete($key);
1303    ///         if (false === $result) {
1304    ///             return false;
1305    ///         }
1306    ///     }
1307    ///     return true;
1308    /// }
1309    /// ```
1310    ///
1311    /// ## PHP 行为对齐
1312    ///
1313    /// - 逐个调用 `delete(key)`,任一失败立即返回 `Err`
1314    /// - 对齐 PHP `if (false === $result) return false`
1315    /// - **注意**:PHP `File::delete` 文件不存在也返回 `false`,导致 `deleteMultiple`
1316    ///   在文件不存在时也返回 `false`(PHP bug)。Rust 端 `delete` 对不存在的 key
1317    ///   返回 `Ok(())`,因此 `delete_many` 对不存在的 key 不会失败(修正 PHP bug)。
1318    ///
1319    /// ## 业务场景对齐
1320    ///
1321    /// 对齐业务场景 4(一次写操作失效多类缓存):
1322    /// ```php
1323    /// // addons/sdp/model/Category.php
1324    /// Cache::delete('sdp_category_tree');
1325    /// Cache::delete('sdp_category_select');
1326    /// Cache::delete('sdp_category_child');
1327    /// Cache::delete('sdp_category_nav');
1328    /// Cache::delete('sdp_category_info:'.$data['cat_id']);
1329    /// ```
1330    ///
1331    /// Rust 端用 `delete_many` 一次调用:
1332    /// ```ignore
1333    /// cache.delete_many(&["sdp_category_tree", "sdp_category_select", "sdp_category_child"])?;
1334    /// ```
1335    pub fn delete_many(&self, keys: &[&str]) -> Result<(), CacheError> {
1336        let mgr = self.manager.read();
1337        let driver = mgr.default_store()?;
1338        for key in keys {
1339            // 对齐 PHP `foreach ($keys as $key) { $result = $this->delete($key); if (false === $result) return false; }`
1340            driver.delete(key)?;
1341        }
1342        Ok(())
1343    }
1344
1345    /// 写操作后失效缓存(对齐 PHP 业务场景 1:事务内写后失效)
1346    ///
1347    /// PHP 业务代码典型模式(`app/food/model/cashier/Clerk.php`):
1348    /// ```php
1349    /// public function add($data): bool
1350    /// {
1351    ///     $this->startTrans();
1352    ///     try {
1353    ///         if($this->save($data)){
1354    ///             Cache::delete('foodCashierClerkAll_' . $data['cashier_id']);
1355    ///             $this->commit();
1356    ///         }
1357    ///     } catch (\Exception $e) {
1358    ///         $this->rollback();
1359    ///     }
1360    /// }
1361    /// ```
1362    ///
1363    /// ## 设计决策
1364    ///
1365    /// - **严禁直接更新缓存**:写操作后应 `delete`(让下次 `get` 时回源),
1366    ///   而非 `set` 更新缓存值(cache-aside 模式)
1367    /// - 返回 `Result<(), CacheError>`:调用方可选择忽略错误(对齐 PHP fire and forget)
1368    /// - 与 `delete_many` 的区别:`invalidate_after_write` 语义明确(写后失效),
1369    ///   便于代码审查和日志追踪
1370    ///
1371    /// ## 用法
1372    ///
1373    /// ```ignore
1374    /// // 写操作后失效相关缓存
1375    /// cache.invalidate_after_write(&["foodCashierClerkAll_1", "foodCashierClerkList_1"])?;
1376    /// // 或 fire and forget(对齐 PHP 业务代码不检查返回值)
1377    /// let _ = cache.invalidate_after_write(&["foodCashierClerkAll_1"]);
1378    /// ```
1379    pub fn invalidate_after_write(&self, keys: &[&str]) -> Result<(), CacheError> {
1380        self.delete_many(keys)
1381    }
1382
1383    /// 先删后读强制刷新(对齐 PHP 业务场景 2:delete → get → 回源 set)
1384    ///
1385    /// PHP 业务代码典型模式(`app/common/model/store/Store.php`):
1386    /// ```php
1387    /// public static function info($store_id){
1388    ///     $cacheKey = 'wmall_store_info_'.$store_id;
1389    ///     Cache::delete($cacheKey);          // 先删
1390    ///     $info = Cache::get($cacheKey);     // 再读(必为空,触发回源)
1391    ///     if(!$info){
1392    ///         $info = $model->with(['supplier','nav'])->find();
1393    ///         if($info){
1394    ///             Cache::set($cacheKey, $info, 86400);
1395    ///         }
1396    ///     }
1397    ///     return $info;
1398    /// }
1399    /// ```
1400    ///
1401    /// ## 设计决策
1402    ///
1403    /// - 优化 PHP 模式:`delete → fetcher() → set`,避免一次无意义的 `get`(PHP 模式中
1404    ///   `delete` 后 `get` 必为空,直接调用 `fetcher` 更高效)
1405    /// - **严禁直接更新缓存**:通过 `delete` + `fetcher` + `set` 实现"强制刷新",
1406    ///   而非直接 `set` 覆盖(确保 fetcher 是唯一数据源)
1407    /// - 返回 `Result<T, CacheError>`:fetcher 失败时传播错误,不写入缓存
1408    ///
1409    /// ## 用法
1410    ///
1411    /// ```ignore
1412    /// # async fn example(cache: &Cache) {
1413    /// let store_info: StoreInfo = cache.refresh("wmall_store_info_1", Some(Duration::from_secs(86400)), || {
1414    ///     // 回源逻辑
1415    ///     Ok(StoreInfo::find(1))
1416    /// })?;
1417    /// # }
1418    /// ```
1419    pub fn refresh<T, F>(
1420        &self,
1421        key: &str,
1422        ttl: Option<Duration>,
1423        fetcher: F,
1424    ) -> Result<T, CacheError>
1425    where
1426        T: Serialize + DeserializeOwned,
1427        F: FnOnce() -> Result<T, CacheError>,
1428    {
1429        // 对齐 PHP Cache::delete($cacheKey) — 先删
1430        self.delete(key)?;
1431
1432        // 对齐 PHP 回源逻辑(PHP 模式中 delete → get 必为空 → 回源)
1433        let value = fetcher()?;
1434
1435        // 对齐 PHP Cache::set($cacheKey, $info, $expire) — 写回缓存
1436        self.set(key, &value, ttl)?;
1437
1438        Ok(value)
1439    }
1440
1441    // ========================================================================
1442    // 缓存击穿/雪崩防护(Rust 特有扩展)
1443    //
1444    // PHP `think\cache\Driver::remember` 有"锁雏形"但缺陷严重:
1445    //   1. 加锁非原子(`$this->set($name.'_lock', true)` 不是 SET NX EX)
1446    //   2. 锁无 TTL(进程崩溃会永久锁死)
1447    //   3. 业务代码 0 处使用 remember
1448    //
1449    // Rust 端用 `parking_lot::Mutex` 实现真正的 singleflight(按 key 互斥),
1450    // 用随机过期时间实现雪崩防护。这是 Rust 特有扩展,对齐 PHP `remember` 的
1451    // "锁意图"但用正确方式实现。
1452    // ========================================================================
1453
1454    /// singleflight 模式回源(Rust 特有扩展,防止缓存击穿)
1455    ///
1456    /// 同一 key 并发请求时,只允许一个线程回源,其他线程等待锁释放后
1457    /// 通过 double-check 从缓存读取结果。
1458    ///
1459    /// ## 与 PHP `remember` 的差异
1460    ///
1461    /// | 维度 | PHP `remember` | Rust `fetch_singleflight` |
1462    /// |------|----------------|---------------------------|
1463    /// | 加锁方式 | `$this->set($name.'_lock', true)` 非原子 | `parking_lot::Mutex::lock()` 原子互斥 |
1464    /// | 锁 TTL | 无(进程崩溃永久锁死) | 无需 TTL(Mutex guard 释放即解锁,panic 自动释放) |
1465    /// | 等待方式 | `while + usleep(200ms)` 轮询 5s 超时 | `Mutex::lock()` 阻塞等待(无超时,但 panic 自动释放) |
1466    /// | double-check | 无 | 有(获取锁后再次检查缓存) |
1467    ///
1468    /// ## 用法
1469    ///
1470    /// ```ignore
1471    /// let value: String = cache.fetch_singleflight("hot_key", Some(Duration::from_secs(60)), || {
1472    ///     // 回源逻辑(数据库查询等)
1473    ///     Ok("expensive_value".to_string())
1474    /// })?;
1475    /// ```
1476    #[tracing::instrument(skip(self, fetcher))]
1477    pub fn fetch_singleflight<T, F>(
1478        &self,
1479        key: &str,
1480        ttl: Option<Duration>,
1481        fetcher: F,
1482    ) -> Result<T, CacheError>
1483    where
1484        T: Serialize + DeserializeOwned,
1485        F: FnOnce() -> Result<T, CacheError>,
1486    {
1487        // 1. 先尝试读缓存(快速路径)
1488        if let Some(cached) = self.get::<T>(key)? {
1489            return Ok(cached);
1490        }
1491
1492        // 2. 获取该 key 的互斥锁(singleflight 核心)
1493        //    inflight map 保证同一 key 的所有请求共享同一个 Arc<Mutex<()>>
1494        let mutex = {
1495            let mut inflight = self.inflight.lock();
1496            inflight
1497                .entry(key.to_string())
1498                .or_insert_with(|| Arc::new(Mutex::new(())))
1499                .clone()
1500        };
1501
1502        // 3. 持有锁执行回源(其他线程在此阻塞等待)
1503        let _guard = mutex.lock();
1504
1505        // 4. double-check:其他线程可能已经回源完成并写入缓存
1506        if let Some(cached) = self.get::<T>(key)? {
1507            return Ok(cached);
1508        }
1509
1510        // 5. 回源并写入缓存
1511        let value = fetcher()?;
1512        self.set(key, &value, ttl)?;
1513
1514        Ok(value)
1515    }
1516
1517    /// 设置带随机抖动的 TTL(Rust 特有扩展,防止缓存雪崩)
1518    ///
1519    /// 在 TTL 上加 `[0, jitter]` 范围的随机抖动,避免大量 key 同时过期触发雪崩。
1520    ///
1521    /// ## 设计决策
1522    ///
1523    /// - PHP 无随机过期时间机制(`getExpireTime` 不做 TTL 抖动)
1524    /// - Rust 特有扩展:用 `rand` crate 生成随机抖动
1525    /// - 实际 TTL 在 `[ttl, ttl + jitter]` 范围内
1526    /// - `jitter` 为 0 时等价于 `set`(无抖动)
1527    /// - `ttl` 为 `None` 时等价于永久缓存(无抖动)
1528    ///
1529    /// ## 用法
1530    ///
1531    /// ```ignore
1532    /// // 基础 TTL 60s + 随机抖动 0-10s(实际 TTL 60-70s)
1533    /// cache.set_with_jitter("key", "value", Some(Duration::from_secs(60)), Duration::from_secs(10))?;
1534    /// ```
1535    pub fn set_with_jitter<T>(
1536        &self,
1537        key: &str,
1538        value: &T,
1539        ttl: Option<Duration>,
1540        jitter: Duration,
1541    ) -> Result<(), CacheError>
1542    where
1543        T: Serialize + ?Sized,
1544    {
1545        let actual_ttl = match ttl {
1546            Some(t) if !jitter.is_zero() => {
1547                // 在 [t, t + jitter] 范围内随机
1548                use rand::Rng;
1549                let jitter_nanos = jitter.as_nanos() as u64;
1550                let random_jitter =
1551                    Duration::from_nanos(rand::thread_rng().gen_range(0..jitter_nanos));
1552                Some(t + random_jitter)
1553            }
1554            Some(t) => Some(t),
1555            None => None,
1556        };
1557        self.set(key, value, actual_ttl)
1558    }
1559
1560    /// singleflight + 随机过期时间组合防护(最完整防护)
1561    ///
1562    /// 组合 `fetch_singleflight`(防击穿)+ `set_with_jitter`(防雪崩),
1563    /// 提供最完整的缓存防护。
1564    ///
1565    /// ## 用法
1566    ///
1567    /// ```ignore
1568    /// let value: String = cache.fetch_with_protection(
1569    ///     "hot_key",
1570    ///     Some(Duration::from_secs(60)),
1571    ///     Duration::from_secs(10),  // 随机抖动 0-10s
1572    ///     || Ok("expensive_value".to_string()),
1573    /// )?;
1574    /// ```
1575    #[tracing::instrument(skip(self, fetcher))]
1576    pub fn fetch_with_protection<T, F>(
1577        &self,
1578        key: &str,
1579        ttl: Option<Duration>,
1580        jitter: Duration,
1581        fetcher: F,
1582    ) -> Result<T, CacheError>
1583    where
1584        T: Serialize + DeserializeOwned,
1585        F: FnOnce() -> Result<T, CacheError>,
1586    {
1587        // 1. 先尝试读缓存(快速路径)
1588        if let Some(cached) = self.get::<T>(key)? {
1589            return Ok(cached);
1590        }
1591
1592        // 2. 获取该 key 的互斥锁(singleflight 核心)
1593        let mutex = {
1594            let mut inflight = self.inflight.lock();
1595            inflight
1596                .entry(key.to_string())
1597                .or_insert_with(|| Arc::new(Mutex::new(())))
1598                .clone()
1599        };
1600
1601        // 3. 持有锁执行回源
1602        let _guard = mutex.lock();
1603
1604        // 4. double-check
1605        if let Some(cached) = self.get::<T>(key)? {
1606            return Ok(cached);
1607        }
1608
1609        // 5. 回源并写入缓存(带随机抖动 TTL)
1610        let value = fetcher()?;
1611        self.set_with_jitter(key, &value, ttl, jitter)?;
1612
1613        Ok(value)
1614    }
1615
1616    // ========================================================================
1617    // 命名 store 访问(对齐 PHP $cache->store('redis')->...)
1618    // ========================================================================
1619
1620    /// 获取命名 store 的代理(对齐 PHP `$cache->store('redis')`)
1621    ///
1622    /// 通过回调方式访问命名 store,避免生命周期问题。
1623    ///
1624    /// ## 示例
1625    ///
1626    /// ```ignore
1627    /// cache.with_store("redis", |driver| {
1628    ///     driver.set_raw("key", b"value".to_vec(), None)
1629    /// }).unwrap();
1630    /// ```
1631    pub fn with_store<R, F>(&self, name: &str, f: F) -> Result<R, CacheError>
1632    where
1633        F: FnOnce(&dyn CacheDriver) -> Result<R, CacheError>,
1634    {
1635        let mgr = self.manager.read();
1636        let driver = mgr.store(name)?;
1637        f(driver)
1638    }
1639
1640    // ========================================================================
1641    // 缓存标签(对齐 PHP think\facade\Cache::tag)
1642    // ========================================================================
1643
1644    /// 缓存标签(对齐 PHP `Driver::tag($name)`)
1645    ///
1646    /// PHP `Driver::tag($name)` 第 196-206 行:
1647    /// ```php
1648    /// public function tag($name): TagSet
1649    /// {
1650    ///     $name = (array) $name;
1651    ///     $key  = implode('-', $name);
1652    ///     if (!isset($this->tag[$key])) {
1653    ///         $this->tag[$key] = new TagSet($name, $this);
1654    ///     }
1655    ///     return $this->tag[$key];
1656    /// }
1657    /// ```
1658    ///
1659    /// ## PHP 单例 vs Rust 实现
1660    ///
1661    /// PHP 使用 `$this->tag[$key]` 单例缓存 `TagSet` 对象,避免重复创建。
1662    /// Rust 端不实现单例(`TagSet` 是无状态结构体,每次创建行为一致),
1663    /// 功能上完全等价。
1664    ///
1665    /// ## 示例
1666    ///
1667    /// ```ignore
1668    /// cache.tag("user").set("user:1", &data, None)?;
1669    /// cache.tag("user").clear();  // 清除所有 user 标签下的缓存
1670    /// ```
1671    pub fn tag(&self, name: &str) -> TagSet<'_> {
1672        TagSet {
1673            tags: vec![name.to_string()],
1674            cache: self,
1675        }
1676    }
1677
1678    /// 多标签缓存(对齐 PHP `Cache::tag(['user', 'admin'])`)
1679    ///
1680    /// PHP `tag($name)` 中 `$name = (array) $name`,支持传入数组。
1681    /// Rust 端通过 `tag_many` 方法提供等价功能。
1682    ///
1683    /// ## 示例
1684    ///
1685    /// ```ignore
1686    /// cache.tag_many(&["user", "admin"]).set("key", &data, None)?;
1687    /// cache.tag_many(&["user", "admin"]).clear();
1688    /// ```
1689    pub fn tag_many(&self, names: &[&str]) -> TagSet<'_> {
1690        TagSet {
1691            tags: names.iter().map(|s| s.to_string()).collect(),
1692            cache: self,
1693        }
1694    }
1695}
1696
1697impl Default for Cache {
1698    fn default() -> Self {
1699        Self::new()
1700    }
1701}
1702
1703// ============================================================================
1704// Trait helper for push deduplication
1705// ============================================================================
1706
1707/// `push` 去重辅助 trait
1708///
1709/// 由于 `T: PartialEq + Clone` 不直接支持 `HashSet`,
1710/// 本 trait 通过 `serde_json::to_string` 生成可哈希的字符串表示。
1711trait CloneHashable: Clone {
1712    fn hashable_string(&self) -> String;
1713}
1714
1715impl<T> CloneHashable for T
1716where
1717    T: Serialize + Clone,
1718{
1719    fn hashable_string(&self) -> String {
1720        serde_json::to_string(self).unwrap_or_default()
1721    }
1722}
1723
1724// ============================================================================
1725// RedisCacheDriver — Redis 驱动(对齐 PHP think\cache\driver\Redis)
1726// ============================================================================
1727//
1728// PHP `think\cache\driver\Redis`(249 行)基于 phpredis 扩展或 Predis\Client,
1729// 提供 Redis 协议级别的缓存操作。核心特性:
1730//
1731// 1. `set` 时 expire > 0 用 SETEX,否则用 SET(对齐 PHP 第 145-149 行)
1732// 2. `inc/dec` 直接 INCRBY/DECRBY(不经 serialize,对齐 PHP 第 161-182 行)
1733// 3. `has` 用 EXISTS(对齐 PHP 第 100-103 行)
1734// 4. `delete` 用 DEL,返回 bool(del 数量 > 0,对齐 PHP 第 190-197 行)
1735// 5. `clear` 用 FLUSHDB(对齐 PHP 第 204-209 行)
1736// 6. `append`(tag)用 SADD(对齐 PHP 第 230-234 行,重写父类 `push` 行为)
1737// 7. `getTagItems` 用 SMEMBERS(对齐 PHP 第 242-247 行)
1738// 8. `clearTag` 用 DEL 批量(对齐 PHP 第 217-221 行)
1739//
1740// ## 架构
1741//
1742// 由于 Rust 端不强制依赖 `redis` crate(避免编译时间增加),本模块通过
1743// `RedisBackend` trait 抽象 Redis 命令,提供 `MockRedisBackend`(用 HashMap
1744// 模拟)作为默认实现。应用层可注入真实 Redis backend(如 `redis::Connection`
1745// 包装)以连接真实 Redis 服务器。
1746
1747use md5::{Digest, Md5};
1748use std::collections::HashSet;
1749
1750/// Redis 缓存配置(对齐 PHP `think\cache\driver\Redis::$options`)
1751///
1752/// PHP 默认配置(Redis.php 第 33-44 行):
1753///
1754/// ```php
1755/// protected $options = [
1756///     'host'       => '127.0.0.1',
1757///     'port'       => 6379,
1758///     'password'   => '',
1759///     'select'     => 0,
1760///     'timeout'    => 0,
1761///     'expire'     => 0,
1762///     'persistent' => false,
1763///     'prefix'     => '',
1764///     'tag_prefix' => 'tag:',
1765///     'serialize'  => [],
1766/// ];
1767/// ```
1768#[derive(Debug, Clone)]
1769pub struct RedisConfig {
1770    /// Redis 主机地址(对齐 PHP `host`)
1771    pub host: String,
1772    /// Redis 端口(对齐 PHP `port`)
1773    pub port: u16,
1774    /// Redis 密码(对齐 PHP `password`,空字符串表示无密码)
1775    pub password: String,
1776    /// Redis db 索引(对齐 PHP `select`)
1777    pub select: u32,
1778    /// 连接超时(对齐 PHP `timeout`,`Duration::ZERO` 表示无超时)
1779    pub timeout: Duration,
1780    /// 默认过期时间(对齐 PHP `expire`,`None` 表示永不过期)
1781    pub expire: Option<Duration>,
1782    /// 是否使用持久连接(对齐 PHP `persistent`)
1783    pub persistent: bool,
1784    /// key 前缀(对齐 PHP `prefix`)
1785    pub prefix: String,
1786    /// tag 前缀(对齐 PHP `tag_prefix`)
1787    pub tag_prefix: String,
1788}
1789
1790impl Default for RedisConfig {
1791    fn default() -> Self {
1792        Self {
1793            host: "127.0.0.1".to_string(),
1794            port: 6379,
1795            password: String::new(),
1796            select: 0,
1797            timeout: Duration::ZERO,
1798            expire: None,
1799            persistent: false,
1800            prefix: String::new(),
1801            tag_prefix: "tag:".to_string(),
1802        }
1803    }
1804}
1805
1806impl RedisConfig {
1807    /// 创建带前缀的配置(便捷方法)
1808    pub fn with_prefix(prefix: impl Into<String>) -> Self {
1809        Self {
1810            prefix: prefix.into(),
1811            ..Default::default()
1812        }
1813    }
1814
1815    /// 创建带默认 TTL 的配置(便捷方法)
1816    pub fn with_expire(expire: Duration) -> Self {
1817        Self {
1818            expire: Some(expire),
1819            ..Default::default()
1820        }
1821    }
1822}
1823
1824/// Redis 后端 trait(抽象 Redis 命令)
1825///
1826/// 由于 Rust 端不强制依赖 `redis` crate,本 trait 抽象 Redis 命令,
1827/// 允许应用层注入真实 Redis backend(如 `redis::Connection` 包装)。
1828///
1829/// ## 默认实现
1830///
1831/// `MockRedisBackend` 用 `HashMap` 模拟 Redis 行为,用于测试和开发环境。
1832///
1833/// ## 命令映射
1834///
1835/// | Trait 方法  | Redis 命令 | PHP phpredis 调用                  |
1836/// |------------|-----------|-----------------------------------|
1837/// | `get`      | GET       | `$handler->get($key)`             |
1838/// | `set`      | SET       | `$handler->set($key, $value)`     |
1839/// | `set_ex`   | SETEX     | `$handler->setex($key, $ttl, $v)` |
1840/// | `del`      | DEL       | `$handler->del($key)`             |
1841/// | `del_many` | DEL ...   | `$handler->del($keys)`            |
1842/// | `exists`   | EXISTS    | `$handler->exists($key)`          |
1843/// | `incr_by`  | INCRBY    | `$handler->incrby($key, $step)`   |
1844/// | `decr_by`  | DECRBY    | `$handler->decrby($key, $step)`   |
1845/// | `flush_db` | FLUSHDB   | `$handler->flushDB()`             |
1846/// | `sadd`     | SADD      | `$handler->sAdd($key, $value)`    |
1847/// | `smembers` | SMEMBERS  | `$handler->sMembers($key)`        |
1848pub trait RedisBackend: Send + Sync {
1849    /// GET 命令
1850    fn get(&self, key: &str) -> Result<Option<Vec<u8>>, CacheError>;
1851    /// SET 命令(无 TTL)
1852    fn set(&self, key: &str, value: Vec<u8>) -> Result<(), CacheError>;
1853    /// SETEX 命令(带 TTL)
1854    fn set_ex(&self, key: &str, value: Vec<u8>, ttl: Duration) -> Result<(), CacheError>;
1855    /// DEL 命令(单个 key),返回删除数量
1856    fn del(&self, key: &str) -> Result<i64, CacheError>;
1857    /// DEL 命令(批量),返回删除数量
1858    fn del_many(&self, keys: &[&str]) -> Result<i64, CacheError>;
1859    /// EXISTS 命令
1860    fn exists(&self, key: &str) -> Result<bool, CacheError>;
1861    /// INCRBY 命令(key 不存在时 Redis 初始化为 0 再 INCRBY)
1862    fn incr_by(&self, key: &str, step: i64) -> Result<i64, CacheError>;
1863    /// DECRBY 命令
1864    fn decr_by(&self, key: &str, step: i64) -> Result<i64, CacheError>;
1865    /// FLUSHDB 命令(清空当前 db)
1866    fn flush_db(&self) -> Result<(), CacheError>;
1867    /// SADD 命令(向 Set 添加成员)
1868    fn sadd(&self, key: &str, member: &str) -> Result<i64, CacheError>;
1869    /// SMEMBERS 命令(返回 Set 全部成员)
1870    fn smembers(&self, key: &str) -> Result<Vec<String>, CacheError>;
1871}
1872
1873/// Mock Redis 后端(用 HashMap 模拟 Redis 行为)
1874///
1875/// 用于测试和开发环境,不需要真实 Redis 服务器。
1876///
1877/// ## 模拟行为
1878///
1879/// - KV 存储:`HashMap<String, (Vec<u8>, Option<Instant>)>` — value + expires_at
1880/// - Set 存储:`HashMap<String, HashSet<String>>`
1881/// - TTL 过期:`get`/`exists`/`incr_by`/`decr_by` 时检查过期
1882/// - INCRBY:key 不存在时初始化为 0,非数字时返回错误(对齐 Redis 行为)
1883pub struct MockRedisBackend {
1884    /// KV 存储:key → (value, expires_at)
1885    kv: parking_lot::RwLock<MockRedisKv>,
1886    /// Set 存储:key → members
1887    sets: parking_lot::RwLock<MockRedisSets>,
1888}
1889
1890/// Mock Redis KV 存储类型(key → (value, expires_at))
1891type MockRedisKv = HashMap<String, (Vec<u8>, Option<Instant>)>;
1892
1893/// Mock Redis Set 存储类型(key → members)
1894type MockRedisSets = HashMap<String, HashSet<String>>;
1895
1896impl Default for MockRedisBackend {
1897    fn default() -> Self {
1898        Self::new()
1899    }
1900}
1901
1902impl MockRedisBackend {
1903    /// 创建新的 Mock Redis 后端
1904    pub fn new() -> Self {
1905        Self {
1906            kv: parking_lot::RwLock::new(HashMap::new()),
1907            sets: parking_lot::RwLock::new(HashMap::new()),
1908        }
1909    }
1910
1911    /// 检查 key 是否已过期(内部辅助,不删除)
1912    fn is_expired(kv: &MockRedisKv, key: &str) -> bool {
1913        if let Some((_, Some(expires_at))) = kv.get(key) {
1914            return *expires_at <= Instant::now();
1915        }
1916        false
1917    }
1918}
1919
1920impl RedisBackend for MockRedisBackend {
1921    fn get(&self, key: &str) -> Result<Option<Vec<u8>>, CacheError> {
1922        let kv = self.kv.read();
1923        if Self::is_expired(&kv, key) {
1924            return Ok(None);
1925        }
1926        Ok(kv.get(key).map(|(v, _)| v.clone()))
1927    }
1928
1929    fn set(&self, key: &str, value: Vec<u8>) -> Result<(), CacheError> {
1930        let mut kv = self.kv.write();
1931        kv.insert(key.to_string(), (value, None));
1932        Ok(())
1933    }
1934
1935    fn set_ex(&self, key: &str, value: Vec<u8>, ttl: Duration) -> Result<(), CacheError> {
1936        let mut kv = self.kv.write();
1937        let expires_at = Some(Instant::now() + ttl);
1938        kv.insert(key.to_string(), (value, expires_at));
1939        Ok(())
1940    }
1941
1942    fn del(&self, key: &str) -> Result<i64, CacheError> {
1943        let mut kv = self.kv.write();
1944        let removed = kv.remove(key).is_some() as i64;
1945        // 同时清理 Set(Redis DEL 会删除所有类型)
1946        let mut sets = self.sets.write();
1947        if sets.remove(key).is_some() && removed == 0 {
1948            return Ok(1);
1949        }
1950        Ok(removed)
1951    }
1952
1953    fn del_many(&self, keys: &[&str]) -> Result<i64, CacheError> {
1954        let mut count = 0i64;
1955        for key in keys {
1956            count += self.del(key)?;
1957        }
1958        Ok(count)
1959    }
1960
1961    fn exists(&self, key: &str) -> Result<bool, CacheError> {
1962        let kv = self.kv.read();
1963        if Self::is_expired(&kv, key) {
1964            return Ok(false);
1965        }
1966        if kv.contains_key(key) {
1967            return Ok(true);
1968        }
1969        let sets = self.sets.read();
1970        Ok(sets.contains_key(key))
1971    }
1972
1973    fn incr_by(&self, key: &str, step: i64) -> Result<i64, CacheError> {
1974        let mut kv = self.kv.write();
1975        // 检查过期:过期则视为不存在
1976        if Self::is_expired(&kv, key) {
1977            kv.remove(key);
1978        }
1979        let current = match kv.get(key) {
1980            Some((bytes, _)) => {
1981                let s = std::str::from_utf8(bytes)
1982                    .map_err(|e| CacheError::DeserializationError(e.to_string()))?;
1983                s.parse::<i64>().map_err(|e| {
1984                    CacheError::Internal(format!("INCRBY failed: '{}' is not an integer: {}", s, e))
1985                })?
1986            }
1987            None => 0, // Redis 对不存在的 key 初始化为 0
1988        };
1989        let new_value = current + step;
1990        kv.insert(key.to_string(), (new_value.to_string().into_bytes(), None));
1991        Ok(new_value)
1992    }
1993
1994    fn decr_by(&self, key: &str, step: i64) -> Result<i64, CacheError> {
1995        // Redis DECRBY 等价于 INCRBY(-step)
1996        self.incr_by(key, -step)
1997    }
1998
1999    fn flush_db(&self) -> Result<(), CacheError> {
2000        let mut kv = self.kv.write();
2001        kv.clear();
2002        let mut sets = self.sets.write();
2003        sets.clear();
2004        Ok(())
2005    }
2006
2007    fn sadd(&self, key: &str, member: &str) -> Result<i64, CacheError> {
2008        let mut sets = self.sets.write();
2009        let set = sets.entry(key.to_string()).or_default();
2010        let added = set.insert(member.to_string()) as i64;
2011        Ok(added)
2012    }
2013
2014    fn smembers(&self, key: &str) -> Result<Vec<String>, CacheError> {
2015        let sets = self.sets.read();
2016        Ok(sets
2017            .get(key)
2018            .map(|s| s.iter().cloned().collect())
2019            .unwrap_or_default())
2020    }
2021}
2022
2023/// Redis 缓存驱动(对齐 PHP `think\cache\driver\Redis`)
2024///
2025/// 基于 `RedisBackend` trait,提供 PHP think-orm Redis 驱动的等价实现。
2026///
2027/// ## PHP 行为对齐
2028///
2029/// 1. **`set` 行为**(PHP 第 133-152 行):
2030///    - `expire > 0` → `SETEX(key, expire, value)`
2031///    - `expire = 0` → `SET(key, value)`
2032///
2033/// 2. **`inc/dec` 行为**(PHP 第 161-182 行):
2034///    - 直接 `INCRBY`/`DECRBY`,**不经 serialize**
2035///    - key 不存在时 Redis 初始化为 0
2036///    - 返回新值(i64)
2037///
2038/// 3. **`has` 行为**(PHP 第 100-103 行):
2039///    - `EXISTS(key)` ? true : false
2040///
2041/// 4. **`delete` 行为**(PHP 第 190-197 行):
2042///    - `DEL(key)` > 0 返回 true
2043///
2044/// 5. **`clear` 行为**(PHP 第 204-209 行):
2045///    - `FLUSHDB()`
2046///
2047/// 6. **`append`(tag)行为**(PHP 第 230-234 行):
2048///    - `SADD(key, value)` — 用 Set 存储 tag 成员
2049///
2050/// 7. **`getTagItems` 行为**(PHP 第 242-247 行):
2051///    - `SMEMBERS(key)` — 返回 Set 全部成员
2052///
2053/// 8. **`clearTag` 行为**(PHP 第 217-221 行):
2054///    - `DEL(keys...)` — 批量删除
2055///
2056/// ## key 构造
2057///
2058/// - `getCacheKey(name)` = `prefix + name`(对齐 PHP `Driver::getCacheKey`)
2059/// - `getTagKey(tag)` = `tag_prefix + md5(tag)`(对齐 PHP `Driver::getTagKey`)
2060///
2061/// ## 使用示例
2062///
2063/// ```ignore
2064/// use sz_rust_core::cache::{RedisCacheDriver, RedisConfig, Cache};
2065///
2066/// let driver = RedisCacheDriver::new(RedisConfig::default());
2067/// let cache = Cache::new();
2068/// cache.register_store("redis", Box::new(driver));
2069/// cache.set_default_store("redis").unwrap();
2070///
2071/// cache.set("key", "value", None).unwrap();
2072/// assert_eq!(cache.get::<String>("key").unwrap(), Some("value".to_string()));
2073/// ```
2074pub struct RedisCacheDriver {
2075    backend: Box<dyn RedisBackend>,
2076    config: RedisConfig,
2077}
2078
2079impl RedisCacheDriver {
2080    /// 创建 Redis 缓存驱动(用 Mock backend)
2081    ///
2082    /// 对齐 PHP `new \think\cache\driver\Redis($options)`。
2083    pub fn new(config: RedisConfig) -> Self {
2084        Self::with_backend(config, Box::new(MockRedisBackend::new()))
2085    }
2086
2087    /// 创建 Redis 缓存驱动(自定义 backend)
2088    ///
2089    /// 应用层可注入真实 Redis backend(如 `redis::Connection` 包装)。
2090    pub fn with_backend(config: RedisConfig, backend: Box<dyn RedisBackend>) -> Self {
2091        Self { backend, config }
2092    }
2093
2094    /// 获取配置引用
2095    pub fn config(&self) -> &RedisConfig {
2096        &self.config
2097    }
2098
2099    /// 获取 backend 引用(用于高级操作)
2100    pub fn backend(&self) -> &dyn RedisBackend {
2101        self.backend.as_ref()
2102    }
2103
2104    /// 追加 TagSet 数据(对齐 PHP `Redis::append`)
2105    ///
2106    /// PHP `Redis::append(name, value)` 第 230-234 行:
2107    /// ```php
2108    /// public function append(string $name, $value): void
2109    /// {
2110    ///     $key = $this->getCacheKey($name);
2111    ///     $this->handler->sAdd($key, $value);
2112    /// }
2113    /// ```
2114    ///
2115    /// **注意**:PHP `think\cache\driver\Redis` 重写了父类 `Driver::append`
2116    /// (父类用 `push`,Redis 驱动用 `SADD`)。
2117    pub fn append(&self, name: &str, value: &str) -> Result<(), CacheError> {
2118        let key = self.get_cache_key(name);
2119        self.backend.sadd(&key, value)?;
2120        Ok(())
2121    }
2122
2123    /// 获取标签包含的缓存标识(对齐 PHP `Redis::getTagItems`)
2124    ///
2125    /// PHP `Redis::getTagItems(tag)` 第 242-247 行:
2126    /// ```php
2127    /// public function getTagItems(string $tag): array
2128    /// {
2129    ///     $name = $this->getTagKey($tag);
2130    ///     $key  = $this->getCacheKey($name);
2131    ///     return $this->handler->sMembers($key);
2132    /// }
2133    /// ```
2134    pub fn get_tag_items(&self, tag: &str) -> Result<Vec<String>, CacheError> {
2135        let name = self.get_tag_key(tag);
2136        let key = self.get_cache_key(&name);
2137        self.backend.smembers(&key)
2138    }
2139
2140    /// 删除缓存标签(对齐 PHP `Redis::clearTag`)
2141    ///
2142    /// PHP `Redis::clearTag(keys)` 第 217-221 行:
2143    /// ```php
2144    /// public function clearTag(array $keys): void
2145    /// {
2146    ///     $this->handler->del($keys);
2147    /// }
2148    /// ```
2149    pub fn clear_tag(&self, keys: &[&str]) -> Result<(), CacheError> {
2150        self.backend.del_many(keys)?;
2151        Ok(())
2152    }
2153
2154    /// 获取 tag key(公开接口,用于测试和调试)
2155    pub fn tag_key(&self, tag: &str) -> String {
2156        self.get_tag_key(tag)
2157    }
2158
2159    /// 获取 cache key(公开接口,用于测试和调试)
2160    pub fn cache_key(&self, name: &str) -> String {
2161        self.get_cache_key(name)
2162    }
2163}
2164
2165impl CacheDriver for RedisCacheDriver {
2166    fn get_raw(&self, key: &str) -> Result<Option<Vec<u8>>, CacheError> {
2167        let cache_key = self.get_cache_key(key);
2168        self.backend.get(&cache_key)
2169    }
2170
2171    fn set_raw(&self, key: &str, value: Vec<u8>, ttl: Option<Duration>) -> Result<(), CacheError> {
2172        let cache_key = self.get_cache_key(key);
2173        // 对齐 PHP: $expire = is_null($ttl) ? $this->options['expire'] : $ttl
2174        let effective_ttl = ttl.or(self.config.expire);
2175        // 对齐 PHP: if ($expire) { setex } else { set }
2176        match effective_ttl {
2177            Some(t) if t > Duration::ZERO => self.backend.set_ex(&cache_key, value, t),
2178            _ => self.backend.set(&cache_key, value),
2179        }
2180    }
2181
2182    fn delete(&self, key: &str) -> Result<(), CacheError> {
2183        let cache_key = self.get_cache_key(key);
2184        // PHP Redis::delete 返回 bool(del 数量 > 0),但 CacheDriver::delete 返回 ()
2185        self.backend.del(&cache_key)?;
2186        Ok(())
2187    }
2188
2189    fn has(&self, key: &str) -> Result<bool, CacheError> {
2190        let cache_key = self.get_cache_key(key);
2191        // 对齐 PHP: return $this->handler->exists($key) ? true : false
2192        self.backend.exists(&cache_key)
2193    }
2194
2195    /// 重写 inc(对齐 PHP `Redis::inc`,直接 INCRBY,不经 serialize)
2196    ///
2197    /// PHP `Redis::inc(name, step)` 第 161-167 行:
2198    /// ```php
2199    /// public function inc(string $name, int $step = 1)
2200    /// {
2201    ///     $this->writeTimes++;
2202    ///     $key = $this->getCacheKey($name);
2203    ///     return $this->handler->incrby($key, $step);
2204    /// }
2205    /// ```
2206    ///
2207    /// **关键差异**:File 驱动读取 → 加减 → 写回(经 serialize 层);
2208    /// Redis 驱动直接 INCRBY(不经 serialize)。Redis 自身处理 key 不存在
2209    /// 的情况(初始化为 0)。
2210    fn inc(&self, key: &str, step: i64) -> Result<i64, CacheError> {
2211        let cache_key = self.get_cache_key(key);
2212        self.backend.incr_by(&cache_key, step)
2213    }
2214
2215    /// 重写 dec(对齐 PHP `Redis::dec`,直接 DECRBY,不经 serialize)
2216    fn dec(&self, key: &str, step: i64) -> Result<i64, CacheError> {
2217        let cache_key = self.get_cache_key(key);
2218        self.backend.decr_by(&cache_key, step)
2219    }
2220
2221    fn clear(&self) -> Result<(), CacheError> {
2222        // 对齐 PHP: $this->handler->flushDB()
2223        self.backend.flush_db()
2224    }
2225
2226    // ========================================================================
2227    // 缓存标签重写(对齐 PHP think\cache\driver\Redis tag 相关方法)
2228    // ========================================================================
2229
2230    /// 重写 `getCacheKey`(对齐 PHP `Driver::getCacheKey`)
2231    ///
2232    /// PHP: `return $this->options['prefix'] . $name;`
2233    fn get_cache_key(&self, name: &str) -> String {
2234        format!("{}{}", self.config.prefix, name)
2235    }
2236
2237    /// 重写 `getTagKey`(对齐 PHP `Driver::getTagKey`)
2238    ///
2239    /// PHP: `return $this->options['tag_prefix'] . md5($tag);`
2240    fn get_tag_key(&self, tag: &str) -> String {
2241        let md5_hex = compute_md5(tag);
2242        format!("{}{}", self.config.tag_prefix, md5_hex)
2243    }
2244
2245    /// 重写 `tag_append`(对齐 PHP `Redis::append`,使用 `sAdd` 而非 `push`)
2246    ///
2247    /// PHP `Redis::append(name, value)` 第 230-234 行:
2248    /// ```php
2249    /// public function append(string $name, $value): void
2250    /// {
2251    ///     $key = $this->getCacheKey($name);
2252    ///     $this->handler->sAdd($key, $value);
2253    /// }
2254    /// ```
2255    ///
2256    /// **关键差异**:PHP `think\cache\driver\Redis` 重写了父类 `Driver::append`
2257    /// (父类用 `push` = get→append→set,Redis 驱动用 `SADD` = 原子 Set 操作)。
2258    fn tag_append(&self, tag_key: &str, cache_key: &str) -> Result<(), CacheError> {
2259        let key = self.get_cache_key(tag_key);
2260        self.backend.sadd(&key, cache_key)?;
2261        Ok(())
2262    }
2263
2264    /// 重写 `tag_items`(对齐 PHP `Redis::getTagItems`,使用 `sMembers`)
2265    ///
2266    /// PHP `Redis::getTagItems(tag)` 第 242-247 行:
2267    /// ```php
2268    /// public function getTagItems(string $tag): array
2269    /// {
2270    ///     $name = $this->getTagKey($tag);
2271    ///     $key  = $this->getCacheKey($name);
2272    ///     return $this->handler->sMembers($key);
2273    /// }
2274    /// ```
2275    fn tag_items(&self, tag: &str) -> Result<Vec<String>, CacheError> {
2276        let name = self.get_tag_key(tag);
2277        let key = self.get_cache_key(&name);
2278        self.backend.smembers(&key)
2279    }
2280
2281    /// 重写 `tag_clear`(对齐 PHP `Redis::clearTag`,raw del 不应用前缀)
2282    ///
2283    /// PHP `Redis::clearTag(keys)` 第 217-221 行:
2284    /// ```php
2285    /// public function clearTag(array $keys): void
2286    /// {
2287    ///     $this->handler->del($keys);
2288    /// }
2289    /// ```
2290    ///
2291    /// **关键**:`keys` 已是 `prefix + name` 格式(来自 `tag_items` 返回值),
2292    /// 因此直接 `del_many`,**不得**再次应用 `getCacheKey`。
2293    fn tag_clear(&self, keys: &[String]) -> Result<(), CacheError> {
2294        let key_refs: Vec<&str> = keys.iter().map(|s| s.as_str()).collect();
2295        self.backend.del_many(&key_refs)?;
2296        Ok(())
2297    }
2298}
2299
2300/// 计算 MD5 哈希(对齐 PHP `md5()` 函数)
2301///
2302/// PHP `md5("hello")` 返回 32 字符小写十六进制字符串。
2303fn compute_md5(s: &str) -> String {
2304    let mut hasher = Md5::new();
2305    hasher.update(s.as_bytes());
2306    let result = hasher.finalize();
2307    hex::encode(result)
2308}
2309
2310// ============================================================================
2311// MultiLevelCacheDriver — 多级缓存驱动(复用 sz_orm_core::MultiLevelCache)
2312// ============================================================================
2313
2314/// 多级缓存驱动(对齐 PHP think-cache 多驱动场景)
2315///
2316/// PHP think-cache 本身没有显式的 MultiLevelCache 概念,但业务层常通过
2317/// `Cache::store('redis')` / `Cache::store('file')` 切换驱动。本驱动封装
2318/// `sz_orm_core::MultiLevelCache`,提供 L1(内存)→ L2(Redis)级联查询:
2319///
2320/// - `get`:从高到低查询,命中后回填低层(带 TTL 保留)
2321/// - `set`:写入所有层级
2322/// - `delete`:删除所有层级
2323/// - `has`:任一层级存在即返回 true
2324/// - `clear`:清空所有层级
2325/// - `inc`/`dec`:委托到第一层(最高级),读取→加减→写回
2326///
2327/// ## 使用示例
2328///
2329/// ```ignore
2330/// use sz_rust_core::cache::{MultiLevelCacheDriver, MemoryCacheDriver};
2331/// use sz_orm_core::MemoryCache;
2332///
2333/// let l1 = MemoryCache::new();
2334/// let l2 = MemoryCache::with_ttl(std::time::Duration::from_secs(60));
2335/// let driver = MultiLevelCacheDriver::new()
2336///     .add_level(Box::new(l1))
2337///     .add_level(Box::new(l2));
2338/// ```
2339pub struct MultiLevelCacheDriver {
2340    inner: sz_orm_core::MultiLevelCache,
2341}
2342
2343impl Default for MultiLevelCacheDriver {
2344    fn default() -> Self {
2345        Self::new()
2346    }
2347}
2348
2349impl MultiLevelCacheDriver {
2350    /// 创建空的多级缓存驱动
2351    pub fn new() -> Self {
2352        Self {
2353            inner: sz_orm_core::MultiLevelCache::new(),
2354        }
2355    }
2356
2357    /// 添加缓存层级(链式调用,先添加的优先级高)
2358    ///
2359    /// 对齐 sz_orm_core::MultiLevelCache::add_cache
2360    pub fn add_level(mut self, cache: Box<dyn InnerCache>) -> Self {
2361        self.inner = self.inner.add_cache(cache);
2362        self
2363    }
2364
2365    /// 获取底层 MultiLevelCache 引用(用于 ttl 等底层查询)
2366    pub fn inner(&self) -> &sz_orm_core::MultiLevelCache {
2367        &self.inner
2368    }
2369}
2370
2371impl CacheDriver for MultiLevelCacheDriver {
2372    fn get_raw(&self, key: &str) -> Result<Option<Vec<u8>>, CacheError> {
2373        self.inner.get(key)
2374    }
2375
2376    fn set_raw(&self, key: &str, value: Vec<u8>, ttl: Option<Duration>) -> Result<(), CacheError> {
2377        self.inner.set(key, value, ttl)
2378    }
2379
2380    fn delete(&self, key: &str) -> Result<(), CacheError> {
2381        self.inner.delete(key)
2382    }
2383
2384    fn has(&self, key: &str) -> Result<bool, CacheError> {
2385        self.inner.exists(key)
2386    }
2387
2388    fn inc(&self, key: &str, step: i64) -> Result<i64, CacheError> {
2389        // 对齐 PHP File 驱动 inc/dec 行为:读取 → 解析为 i64 → 加减 → 写回
2390        // 多级缓存下,inc/dec 委托到第一层(最高级)
2391        let current = match self.inner.get(key)? {
2392            Some(bytes) => String::from_utf8(bytes)
2393                .map_err(|e| CacheError::DeserializationError(e.to_string()))?
2394                .parse::<i64>()
2395                .unwrap_or(0),
2396            None => 0,
2397        };
2398        let new_value = current + step;
2399        let new_bytes = new_value.to_string().into_bytes();
2400        // 保留原 TTL:查询第一层的 ttl,写回时不重新设置
2401        let ttl = self.inner.ttl(key).ok().flatten();
2402        self.inner.set(key, new_bytes, ttl)?;
2403        Ok(new_value)
2404    }
2405
2406    fn dec(&self, key: &str, step: i64) -> Result<i64, CacheError> {
2407        // 对齐 PHP File 驱动:读取 → 解析为 i64 → 减 → 写回
2408        let current = match self.inner.get(key)? {
2409            Some(bytes) => String::from_utf8(bytes)
2410                .map_err(|e| CacheError::DeserializationError(e.to_string()))?
2411                .parse::<i64>()
2412                .unwrap_or(0),
2413            None => 0,
2414        };
2415        let new_value = current - step;
2416        let new_bytes = new_value.to_string().into_bytes();
2417        let ttl = self.inner.ttl(key).ok().flatten();
2418        self.inner.set(key, new_bytes, ttl)?;
2419        Ok(new_value)
2420    }
2421
2422    fn clear(&self) -> Result<(), CacheError> {
2423        self.inner.clear()
2424    }
2425}
2426
2427// ============================================================================
2428// TagSet — 缓存标签集合(对齐 PHP think\cache\TagSet)
2429// ============================================================================
2430
2431/// 缓存标签集合(对齐 PHP `think\cache\TagSet`)
2432///
2433/// PHP `TagSet`(132 行)提供基于标签的缓存批量管理:
2434///
2435/// - `set(name, value, expire)`:写入缓存 + 追加 key 到标签集合
2436/// - `append(name)`:追加 key 到所有标签
2437/// - `clear()`:清除所有标签下的缓存
2438///
2439/// ## PHP 对齐
2440///
2441/// PHP `TagSet::set` 第 52-59 行:
2442/// ```php
2443/// public function set(string $name, $value, $expire = null): bool
2444/// {
2445///     $this->handler->set($name, $value, $expire);
2446///     $this->append($name);
2447///     return true;
2448/// }
2449/// ```
2450///
2451/// PHP `TagSet::append` 第 67-75 行:
2452/// ```php
2453/// public function append(string $name): void
2454/// {
2455///     $name = $this->handler->getCacheKey($name);
2456///     foreach ($this->tag as $tag) {
2457///         $key = $this->handler->getTagKey($tag);
2458///         $this->handler->append($key, $name);
2459///     }
2460/// }
2461/// ```
2462///
2463/// PHP `TagSet::clear` 第 119-131 行:
2464/// ```php
2465/// public function clear(): bool
2466/// {
2467///     foreach ($this->tag as $tag) {
2468///         $names = $this->handler->getTagItems($tag);
2469///         $this->handler->clearTag($names);
2470///         $key = $this->handler->getTagKey($tag);
2471///         $this->handler->delete($key);
2472///     }
2473///     return true;
2474/// }
2475/// ```
2476///
2477/// ## 生命周期
2478///
2479/// `TagSet<'a>` 持有 `&'a Cache` 引用,确保在 TagSet 使用期间 Cache 不会被释放。
2480/// 通过 `Cache::tag()` 或 `Cache::tag_many()` 创建。
2481pub struct TagSet<'a> {
2482    /// 标签名列表(对齐 PHP `TagSet::$tag`)
2483    tags: Vec<String>,
2484    /// 缓存句柄(对齐 PHP `TagSet::$handler`)
2485    cache: &'a Cache,
2486}
2487
2488impl<'a> TagSet<'a> {
2489    /// 写入缓存并追加到标签(对齐 PHP `TagSet::set`)
2490    ///
2491    /// PHP `TagSet::set(name, value, expire)` 第 52-59 行:
2492    /// 1. `handler->set(name, value, expire)` — 写入缓存
2493    /// 2. `append(name)` — 追加 key 到所有标签
2494    ///
2495    /// ## 参数
2496    ///
2497    /// - `key`:缓存键
2498    /// - `value`:缓存值(实现 `Serialize`)
2499    /// - `ttl`:过期时间(`None` 永不过期)
2500    pub fn set<T: Serialize>(
2501        &self,
2502        key: &str,
2503        value: T,
2504        ttl: Option<Duration>,
2505    ) -> Result<(), CacheError> {
2506        // 对齐 PHP: $this->handler->set($name, $value, $expire);
2507        self.cache.set(key, value, ttl)?;
2508        // 对齐 PHP: $this->append($name);
2509        self.append(key)
2510    }
2511
2512    /// 追加缓存 key 到所有标签(对齐 PHP `TagSet::append`)
2513    ///
2514    /// PHP `TagSet::append(name)` 第 67-75 行:
2515    /// ```php
2516    /// $name = $this->handler->getCacheKey($name);
2517    /// foreach ($this->tag as $tag) {
2518    ///     $key = $this->handler->getTagKey($tag);
2519    ///     $this->handler->append($key, $name);
2520    /// }
2521    /// ```
2522    ///
2523    /// ## 行为
2524    ///
2525    /// 1. 计算 `cache_key = getCacheKey(name)`(应用前缀)
2526    /// 2. 对每个 tag:计算 `tag_key = getTagKey(tag)`,调用 `driver.tag_append(tag_key, cache_key)`
2527    pub fn append(&self, key: &str) -> Result<(), CacheError> {
2528        let mgr = self.cache.manager.read();
2529        let driver = mgr.default_store()?;
2530        // 对齐 PHP: $name = $this->handler->getCacheKey($name);
2531        let cache_key = driver.get_cache_key(key);
2532        // 对齐 PHP: foreach ($this->tag as $tag) { ... }
2533        for tag in &self.tags {
2534            // 对齐 PHP: $key = $this->handler->getTagKey($tag);
2535            let tag_key = driver.get_tag_key(tag);
2536            // 对齐 PHP: $this->handler->append($key, $name);
2537            driver.tag_append(&tag_key, &cache_key)?;
2538        }
2539        Ok(())
2540    }
2541
2542    /// 清除所有标签下的缓存(对齐 PHP `TagSet::clear`)
2543    ///
2544    /// PHP `TagSet::clear()` 第 119-131 行:
2545    /// ```php
2546    /// foreach ($this->tag as $tag) {
2547    ///     $names = $this->handler->getTagItems($tag);
2548    ///     $this->handler->clearTag($names);
2549    ///     $key = $this->handler->getTagKey($tag);
2550    ///     $this->handler->delete($key);
2551    /// }
2552    /// ```
2553    ///
2554    /// ## 行为
2555    ///
2556    /// 对每个 tag:
2557    /// 1. `tag_items(tag)` — 获取该标签下所有缓存 key(已应用前缀)
2558    /// 2. `tag_clear(items)` — 批量删除这些缓存 key(raw delete,不应用前缀)
2559    /// 3. `delete(get_tag_key(tag))` — 删除标签 key 本身(delete 应用前缀)
2560    pub fn clear(&self) -> Result<(), CacheError> {
2561        let mgr = self.cache.manager.read();
2562        let driver = mgr.default_store()?;
2563        for tag in &self.tags {
2564            // 对齐 PHP: $names = $this->handler->getTagItems($tag);
2565            let items = driver.tag_items(tag)?;
2566            // 对齐 PHP: $this->handler->clearTag($names);
2567            driver.tag_clear(&items)?;
2568            // 对齐 PHP: $key = $this->handler->getTagKey($tag);
2569            let tag_key = driver.get_tag_key(tag);
2570            // 对齐 PHP: $this->handler->delete($key);
2571            driver.delete(&tag_key)?;
2572        }
2573        Ok(())
2574    }
2575
2576    /// 获取标签列表(用于测试和调试)
2577    pub fn tags(&self) -> &[String] {
2578        &self.tags
2579    }
2580}
2581
2582// ============================================================================
2583// 单元测试
2584// ============================================================================
2585
2586#[cfg(test)]
2587mod tests {
2588    use super::*;
2589    use serde::Deserialize;
2590    use std::sync::Barrier;
2591
2592    /// 创建带默认驱动的测试用 Cache
2593    fn make_cache() -> Cache {
2594        let cache = Cache::new();
2595        cache.register_default(MemoryCacheDriver::new());
2596        cache
2597    }
2598
2599    // ========================================================================
2600    // 组 1:php_is_numeric 对齐 PHP is_numeric
2601    // ========================================================================
2602
2603    #[test]
2604    fn test_php_is_numeric_integer() {
2605        // 对齐 PHP: is_numeric("42") === true
2606        assert!(php_is_numeric("42"));
2607        assert!(php_is_numeric("-42"));
2608        assert!(php_is_numeric("+42"));
2609        assert!(php_is_numeric("0"));
2610    }
2611
2612    #[test]
2613    fn test_php_is_numeric_float() {
2614        // 对齐 PHP: is_numeric("3.14") === true
2615        assert!(php_is_numeric("3.14"));
2616        assert!(php_is_numeric("-3.14"));
2617        assert!(php_is_numeric("+3.14"));
2618        assert!(php_is_numeric("0.0"));
2619    }
2620
2621    #[test]
2622    fn test_php_is_numeric_scientific_notation() {
2623        // 对齐 PHP: is_numeric("1e10") === true
2624        assert!(php_is_numeric("1e10"));
2625        assert!(php_is_numeric("1.5E-3"));
2626    }
2627
2628    #[test]
2629    fn test_php_is_numeric_non_numeric() {
2630        // 对齐 PHP: is_numeric("abc") === false
2631        assert!(!php_is_numeric("abc"));
2632        assert!(!php_is_numeric("12abc"));
2633        assert!(!php_is_numeric(""));
2634        assert!(!php_is_numeric("0x1A")); // PHP 7+ 不识别十六进制字符串
2635        assert!(!php_is_numeric("null"));
2636        assert!(!php_is_numeric("true"));
2637    }
2638
2639    // ========================================================================
2640    // 组 2:php_serialize / php_unserialize 序列化策略
2641    // ========================================================================
2642
2643    #[test]
2644    fn test_php_serialize_integer_to_number() {
2645        // 对齐 PHP: serialize(42) === "42"(is_numeric 短路)
2646        let v = php_serialize(&42i64).unwrap();
2647        assert!(matches!(v, CacheValue::Number(_)));
2648        if let CacheValue::Number(s) = v {
2649            assert_eq!(s, "42");
2650        }
2651    }
2652
2653    #[test]
2654    fn test_php_serialize_float_to_number() {
2655        // 对齐 PHP: serialize(2.5) === "2.5"(is_numeric 短路)
2656        // 注:避开 3.14(clippy approx_constant 误报为 PI 近似值)
2657        let v = php_serialize(&2.5f64).unwrap();
2658        assert!(matches!(v, CacheValue::Number(_)));
2659        if let CacheValue::Number(s) = v {
2660            assert_eq!(s, "2.5");
2661        }
2662    }
2663
2664    #[test]
2665    fn test_php_serialize_string_to_json() {
2666        // 对齐 PHP: serialize("Alice") === 's:5:"Alice";'(非 numeric 走 serialize)
2667        // Rust 端用 serde_json,"Alice" → "\"Alice\""
2668        let v = php_serialize(&"Alice".to_string()).unwrap();
2669        assert!(matches!(v, CacheValue::Json(_)));
2670        if let CacheValue::Json(s) = v {
2671            assert_eq!(s, "\"Alice\"");
2672        }
2673    }
2674
2675    #[test]
2676    fn test_php_serialize_numeric_string_to_number() {
2677        // PHP is_numeric("42") === true,但 serde_json 序列化 String "42" → "\"42\""(带引号)
2678        // 因此 Rust 端把 String "42" 视为非 numeric,存为 Json
2679        // 这是 PHP 与 Rust 序列化机制的差异:PHP serialize 直接接收 $data 值,
2680        // 若 $data 是字符串 "42",PHP is_numeric 检查的是字符串内容 "42"(true)
2681        // Rust serde_json 序列化 String "42" → "\"42\""(带引号),php_is_numeric 检查的是 "\"42\""(false)
2682        //
2683        // 这个差异是预期的:PHP 的 $value 是弱类型,Rust 的 T: Serialize 是强类型。
2684        // 业务对齐通过 i64/f64 类型直接调用 set 来保证 is_numeric 短路生效。
2685        let v = php_serialize(&"42".to_string()).unwrap();
2686        assert!(matches!(v, CacheValue::Json(_))); // 注意:是 Json,不是 Number
2687    }
2688
2689    #[test]
2690    fn test_php_serialize_array_to_json() {
2691        // 对齐 PHP: serialize([1, 2, 3])(非 numeric 走 serialize)
2692        let v = php_serialize(&vec![1, 2, 3]).unwrap();
2693        assert!(matches!(v, CacheValue::Json(_)));
2694        if let CacheValue::Json(s) = v {
2695            assert_eq!(s, "[1,2,3]");
2696        }
2697    }
2698
2699    #[test]
2700    fn test_php_unserialize_number_returns_string() {
2701        // PHP bug 复刻:unserialize 对 is_numeric 返回 string,而非 int
2702        // Rust 端通过泛型 T = String 来对齐
2703        let v = CacheValue::Number("42".to_string());
2704        let result: Option<String> = php_unserialize(&v).unwrap();
2705        assert_eq!(result, Some("42".to_string()));
2706    }
2707
2708    #[test]
2709    fn test_php_unserialize_json_returns_struct() {
2710        // unserialize 对 JSON 字符串还原为原始结构
2711        let v = CacheValue::Json("\"Alice\"".to_string());
2712        let result: Option<String> = php_unserialize(&v).unwrap();
2713        assert_eq!(result, Some("Alice".to_string()));
2714
2715        let v = CacheValue::Json("[1,2,3]".to_string());
2716        let result: Option<Vec<i64>> = php_unserialize(&v).unwrap();
2717        assert_eq!(result, Some(vec![1, 2, 3]));
2718    }
2719
2720    #[test]
2721    fn test_php_unserialize_number_to_int_via_parse() {
2722        // 对齐 PHP 业务代码 (int) Cache::get('count') 强转模式
2723        // Rust 端:get::<String>() + .parse::<i64>()
2724        let v = CacheValue::Number("42".to_string());
2725        let s: String = php_unserialize(&v).unwrap().unwrap();
2726        let n: i64 = s.parse().unwrap();
2727        assert_eq!(n, 42);
2728    }
2729
2730    // ========================================================================
2731    // 组 3:CacheValue from_bytes / to_bytes 往返
2732    // ========================================================================
2733
2734    #[test]
2735    fn test_cache_value_number_roundtrip() {
2736        let v = CacheValue::Number("42".to_string());
2737        let bytes = v.to_bytes();
2738        let restored = CacheValue::from_bytes(&bytes).unwrap();
2739        assert_eq!(v, restored);
2740    }
2741
2742    #[test]
2743    fn test_cache_value_json_roundtrip() {
2744        let v = CacheValue::Json("\"Alice\"".to_string());
2745        let bytes = v.to_bytes();
2746        let restored = CacheValue::from_bytes(&bytes).unwrap();
2747        assert_eq!(v, restored);
2748    }
2749
2750    #[test]
2751    fn test_cache_value_array_roundtrip() {
2752        let v = CacheValue::Json("[1,2,3]".to_string());
2753        let bytes = v.to_bytes();
2754        let restored = CacheValue::from_bytes(&bytes).unwrap();
2755        assert_eq!(v, restored);
2756    }
2757
2758    #[test]
2759    fn test_cache_value_from_bytes_numeric_string_becomes_number() {
2760        // "42" 字节 → Number(对齐 PHP unserialize is_numeric 短路)
2761        let bytes = b"42".to_vec();
2762        let v = CacheValue::from_bytes(&bytes).unwrap();
2763        assert!(matches!(v, CacheValue::Number(_)));
2764    }
2765
2766    #[test]
2767    fn test_cache_value_from_bytes_json_string_becomes_json() {
2768        // "\"Alice\"" 字节 → Json
2769        let bytes = b"\"Alice\"".to_vec();
2770        let v = CacheValue::from_bytes(&bytes).unwrap();
2771        assert!(matches!(v, CacheValue::Json(_)));
2772    }
2773
2774    // ========================================================================
2775    // 组 4:MemoryCacheDriver 基本操作
2776    // ========================================================================
2777
2778    #[test]
2779    fn test_memory_driver_set_get_raw() {
2780        let driver = MemoryCacheDriver::new();
2781        driver.set_raw("key", b"value".to_vec(), None).unwrap();
2782        let val = driver.get_raw("key").unwrap();
2783        assert_eq!(val, Some(b"value".to_vec()));
2784    }
2785
2786    #[test]
2787    fn test_memory_driver_delete() {
2788        let driver = MemoryCacheDriver::new();
2789        driver.set_raw("key", b"value".to_vec(), None).unwrap();
2790        driver.delete("key").unwrap();
2791        let val = driver.get_raw("key").unwrap();
2792        assert_eq!(val, None);
2793    }
2794
2795    #[test]
2796    fn test_memory_driver_has() {
2797        let driver = MemoryCacheDriver::new();
2798        driver.set_raw("key", b"value".to_vec(), None).unwrap();
2799        assert!(driver.has("key").unwrap());
2800        assert!(!driver.has("nonexistent").unwrap());
2801    }
2802
2803    #[test]
2804    fn test_memory_driver_clear() {
2805        let driver = MemoryCacheDriver::new();
2806        driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
2807        driver.set_raw("key2", b"value2".to_vec(), None).unwrap();
2808        driver.clear().unwrap();
2809        assert!(!driver.has("key1").unwrap());
2810        assert!(!driver.has("key2").unwrap());
2811    }
2812
2813    #[test]
2814    fn test_memory_driver_ttl_expiration() {
2815        let driver = MemoryCacheDriver::new();
2816        driver
2817            .set_raw("key", b"value".to_vec(), Some(Duration::from_millis(50)))
2818            .unwrap();
2819        assert!(driver.get_raw("key").unwrap().is_some());
2820        std::thread::sleep(Duration::from_millis(100));
2821        assert!(driver.get_raw("key").unwrap().is_none());
2822    }
2823
2824    #[test]
2825    fn test_memory_driver_inc_default_implementation() {
2826        // 默认实现:File 驱动行为(读取 → 加减 → 写回)
2827        let driver = MemoryCacheDriver::new();
2828
2829        // 键不存在:初始化为 step
2830        let v = driver.inc("counter", 5).unwrap();
2831        assert_eq!(v, 5);
2832
2833        // 键存在:加 step
2834        let v = driver.inc("counter", 3).unwrap();
2835        assert_eq!(v, 8);
2836    }
2837
2838    #[test]
2839    fn test_memory_driver_dec_default_implementation() {
2840        let driver = MemoryCacheDriver::new();
2841
2842        // 键不存在:初始化为 -step(即 0 - step)
2843        let v = driver.dec("counter", 3).unwrap();
2844        assert_eq!(v, -3);
2845
2846        // 键存在:减 step
2847        let v = driver.dec("counter", 2).unwrap();
2848        assert_eq!(v, -5);
2849    }
2850
2851    // ========================================================================
2852    // 组 5:CacheManager 多驱动管理
2853    // ========================================================================
2854
2855    #[test]
2856    fn test_cache_manager_register_and_get_default() {
2857        let mut mgr = CacheManager::new();
2858        mgr.register_store("default", Box::new(MemoryCacheDriver::new()));
2859
2860        let driver = mgr.default_store().unwrap();
2861        driver.set_raw("key", b"value".to_vec(), None).unwrap();
2862        assert_eq!(driver.get_raw("key").unwrap(), Some(b"value".to_vec()));
2863    }
2864
2865    #[test]
2866    fn test_cache_manager_multiple_stores_isolation() {
2867        let mut mgr = CacheManager::new();
2868        mgr.register_store("file", Box::new(MemoryCacheDriver::new()));
2869        mgr.register_store("redis", Box::new(MemoryCacheDriver::new()));
2870
2871        let file_driver = mgr.store("file").unwrap();
2872        let redis_driver = mgr.store("redis").unwrap();
2873
2874        file_driver
2875            .set_raw("key", b"file_value".to_vec(), None)
2876            .unwrap();
2877        redis_driver
2878            .set_raw("key", b"redis_value".to_vec(), None)
2879            .unwrap();
2880
2881        // 不同 store 隔离
2882        assert_eq!(
2883            file_driver.get_raw("key").unwrap(),
2884            Some(b"file_value".to_vec())
2885        );
2886        assert_eq!(
2887            redis_driver.get_raw("key").unwrap(),
2888            Some(b"redis_value".to_vec())
2889        );
2890    }
2891
2892    #[test]
2893    fn test_cache_manager_set_default() {
2894        let mut mgr = CacheManager::new();
2895        mgr.register_store("file", Box::new(MemoryCacheDriver::new()));
2896        mgr.register_store("redis", Box::new(MemoryCacheDriver::new()));
2897
2898        // 默认是第一个注册的(file)
2899        let driver = mgr.default_store().unwrap();
2900        driver.set_raw("file_key", b"file".to_vec(), None).unwrap();
2901        assert_eq!(driver.get_raw("file_key").unwrap(), Some(b"file".to_vec()));
2902
2903        // 切换默认到 redis
2904        mgr.set_default("redis").unwrap();
2905        let driver = mgr.default_store().unwrap();
2906        driver
2907            .set_raw("redis_key", b"redis".to_vec(), None)
2908            .unwrap();
2909        assert_eq!(
2910            driver.get_raw("redis_key").unwrap(),
2911            Some(b"redis".to_vec())
2912        );
2913    }
2914
2915    #[test]
2916    fn test_cache_manager_default_store_not_registered_error() {
2917        let mgr = CacheManager::new();
2918        let result = mgr.default_store();
2919        assert!(matches!(result, Err(CacheError::NotFound(_))));
2920    }
2921
2922    #[test]
2923    fn test_cache_manager_store_not_found_error() {
2924        let mgr = CacheManager::new();
2925        let result = mgr.store("nonexistent");
2926        assert!(matches!(result, Err(CacheError::NotFound(_))));
2927    }
2928
2929    // ========================================================================
2930    // 组 6:Cache facade set/get 基本 API
2931    // ========================================================================
2932
2933    #[test]
2934    fn test_cache_set_get_string() {
2935        let cache = make_cache();
2936        cache.set("name", "Alice", None).unwrap();
2937        let val: Option<String> = cache.get("name").unwrap();
2938        assert_eq!(val, Some("Alice".to_string()));
2939    }
2940
2941    #[test]
2942    fn test_cache_set_get_int_as_string_php_bug() {
2943        // PHP bug 复刻:is_numeric 短路 + unserialize 返回 string
2944        // 调用方需自行 parse::<i64>()
2945        let cache = make_cache();
2946        cache.set("count", 42i64, None).unwrap();
2947
2948        // 直接 get::<i64> 会失败(PHP 也不允许,需 (int) 强转)
2949        // 对齐方式:get::<String> + parse::<i64>
2950        let s: Option<String> = cache.get("count").unwrap();
2951        assert_eq!(s, Some("42".to_string()));
2952
2953        let n: i64 = s.unwrap().parse().unwrap();
2954        assert_eq!(n, 42);
2955    }
2956
2957    #[test]
2958    fn test_cache_set_get_struct() {
2959        #[derive(Serialize, Deserialize, PartialEq, Debug)]
2960        struct User {
2961            name: String,
2962            age: u32,
2963        }
2964
2965        let cache = make_cache();
2966        let user = User {
2967            name: "Alice".to_string(),
2968            age: 30,
2969        };
2970        cache.set("user:1", &user, None).unwrap();
2971
2972        let val: Option<User> = cache.get("user:1").unwrap();
2973        assert_eq!(val, Some(user));
2974    }
2975
2976    #[test]
2977    fn test_cache_set_get_vec() {
2978        let cache = make_cache();
2979        let list = vec![1, 2, 3];
2980        cache.set("list", &list, None).unwrap();
2981
2982        let val: Option<Vec<i64>> = cache.get("list").unwrap();
2983        assert_eq!(val, Some(vec![1, 2, 3]));
2984    }
2985
2986    #[test]
2987    fn test_cache_get_miss_returns_none() {
2988        let cache = make_cache();
2989        let val: Option<String> = cache.get("nonexistent").unwrap();
2990        assert_eq!(val, None);
2991    }
2992
2993    #[test]
2994    fn test_cache_get_or_default_value() {
2995        let cache = make_cache();
2996        let val: String = cache.get_or("nonexistent", "default".to_string()).unwrap();
2997        assert_eq!(val, "default");
2998    }
2999
3000    #[test]
3001    fn test_cache_set_with_ttl_expires() {
3002        let cache = make_cache();
3003        cache
3004            .set("key", "value", Some(Duration::from_millis(50)))
3005            .unwrap();
3006        assert!(cache.get::<String>("key").unwrap().is_some());
3007        std::thread::sleep(Duration::from_millis(100));
3008        assert!(cache.get::<String>("key").unwrap().is_none());
3009    }
3010
3011    // ========================================================================
3012    // 组 7:Cache facade delete / has / clear
3013    // ========================================================================
3014
3015    #[test]
3016    fn test_cache_delete() {
3017        let cache = make_cache();
3018        cache.set("key", "value", None).unwrap();
3019        assert!(cache.has("key").unwrap());
3020
3021        cache.delete("key").unwrap();
3022        assert!(!cache.has("key").unwrap());
3023
3024        // 删除不存在的 key 不报错(对齐 PHP)
3025        cache.delete("nonexistent").unwrap();
3026    }
3027
3028    #[test]
3029    fn test_cache_has_checks_ttl() {
3030        let cache = make_cache();
3031        cache
3032            .set("key", "value", Some(Duration::from_millis(50)))
3033            .unwrap();
3034        assert!(cache.has("key").unwrap());
3035
3036        std::thread::sleep(Duration::from_millis(100));
3037        // TTL 过期后 has 返回 false
3038        assert!(!cache.has("key").unwrap());
3039    }
3040
3041    #[test]
3042    fn test_cache_clear() {
3043        let cache = make_cache();
3044        cache.set("key1", "value1", None).unwrap();
3045        cache.set("key2", "value2", None).unwrap();
3046
3047        cache.clear().unwrap();
3048
3049        assert!(!cache.has("key1").unwrap());
3050        assert!(!cache.has("key2").unwrap());
3051    }
3052
3053    // ========================================================================
3054    // 组 8:Cache facade inc / dec
3055    // ========================================================================
3056
3057    #[test]
3058    fn test_cache_inc_initial_value() {
3059        // 对齐 PHP: 键不存在时初始化为 step
3060        let cache = make_cache();
3061        let v = cache.inc("counter", 5).unwrap();
3062        assert_eq!(v, 5);
3063
3064        // 验证存储的值
3065        let s: String = cache.get("counter").unwrap().unwrap();
3066        assert_eq!(s, "5");
3067    }
3068
3069    #[test]
3070    fn test_cache_inc_accumulate() {
3071        let cache = make_cache();
3072        cache.inc("counter", 5).unwrap();
3073        cache.inc("counter", 3).unwrap();
3074        let v = cache.inc("counter", 2).unwrap();
3075        assert_eq!(v, 10);
3076    }
3077
3078    #[test]
3079    fn test_cache_dec_initial_value() {
3080        // 对齐 PHP: 键不存在时初始化为 -step
3081        let cache = make_cache();
3082        let v = cache.dec("counter", 3).unwrap();
3083        assert_eq!(v, -3);
3084    }
3085
3086    #[test]
3087    fn test_cache_dec_accumulate() {
3088        let cache = make_cache();
3089        cache.set("counter", 100i64, None).unwrap();
3090        cache.dec("counter", 30).unwrap();
3091        let v = cache.dec("counter", 20).unwrap();
3092        assert_eq!(v, 50);
3093    }
3094
3095    #[test]
3096    fn test_cache_increment_default_step_1() {
3097        let cache = make_cache();
3098        let v = cache.increment("counter").unwrap();
3099        assert_eq!(v, 1);
3100        let v = cache.increment("counter").unwrap();
3101        assert_eq!(v, 2);
3102    }
3103
3104    #[test]
3105    fn test_cache_decrement_default_step_1() {
3106        let cache = make_cache();
3107        let v = cache.decrement("counter").unwrap();
3108        assert_eq!(v, -1);
3109        let v = cache.decrement("counter").unwrap();
3110        assert_eq!(v, -2);
3111    }
3112
3113    // ========================================================================
3114    // 组 9:Cache facade pull(读后删)
3115    // ========================================================================
3116
3117    #[test]
3118    fn test_cache_pull_existing_key() {
3119        // 对齐 PHP: get + delete
3120        let cache = make_cache();
3121        cache.set("key", "value", None).unwrap();
3122
3123        let val: Option<String> = cache.pull("key").unwrap();
3124        assert_eq!(val, Some("value".to_string()));
3125
3126        // pull 后 key 应被删除
3127        assert!(!cache.has("key").unwrap());
3128    }
3129
3130    #[test]
3131    fn test_cache_pull_missing_key_returns_none() {
3132        let cache = make_cache();
3133        let val: Option<String> = cache.pull("nonexistent").unwrap();
3134        assert_eq!(val, None);
3135    }
3136
3137    // ========================================================================
3138    // 组 10:Cache facade push(数组追加 + 上限 + 去重)
3139    // ========================================================================
3140
3141    #[test]
3142    fn test_cache_push_initial_array() {
3143        let cache = make_cache();
3144        cache.push("list", "a".to_string(), None).unwrap();
3145
3146        let val: Option<Vec<String>> = cache.get("list").unwrap();
3147        assert_eq!(val, Some(vec!["a".to_string()]));
3148    }
3149
3150    #[test]
3151    fn test_cache_push_appends() {
3152        let cache = make_cache();
3153        cache.push("list", "a".to_string(), None).unwrap();
3154        cache.push("list", "b".to_string(), None).unwrap();
3155        cache.push("list", "c".to_string(), None).unwrap();
3156
3157        let val: Option<Vec<String>> = cache.get("list").unwrap();
3158        assert_eq!(
3159            val,
3160            Some(vec!["a".to_string(), "b".to_string(), "c".to_string()])
3161        );
3162    }
3163
3164    #[test]
3165    fn test_cache_push_deduplication() {
3166        // 对齐 PHP array_unique:保留首次出现的元素
3167        let cache = make_cache();
3168        cache.push("list", "a".to_string(), None).unwrap();
3169        cache.push("list", "b".to_string(), None).unwrap();
3170        cache.push("list", "a".to_string(), None).unwrap(); // 重复
3171        cache.push("list", "c".to_string(), None).unwrap();
3172        cache.push("list", "b".to_string(), None).unwrap(); // 重复
3173
3174        let val: Option<Vec<String>> = cache.get("list").unwrap();
3175        assert_eq!(
3176            val,
3177            Some(vec!["a".to_string(), "b".to_string(), "c".to_string()])
3178        );
3179    }
3180
3181    #[test]
3182    fn test_cache_push_max_1000_fifo() {
3183        // 对齐 PHP array_shift:长度 > 1000 时丢弃最旧
3184        let cache = make_cache();
3185
3186        // 推入 1001 个元素
3187        for i in 0..1001i64 {
3188            cache.push("list", i, None).unwrap();
3189        }
3190
3191        let val: Option<Vec<i64>> = cache.get("list").unwrap();
3192        let list = val.unwrap();
3193
3194        // 长度应为 1000(丢弃了 0)
3195        assert_eq!(list.len(), 1000);
3196        // 第一个元素应为 1(0 被丢弃)
3197        assert_eq!(list[0], 1);
3198        // 最后一个元素应为 1000
3199        assert_eq!(list[999], 1000);
3200    }
3201
3202    #[test]
3203    fn test_cache_push_non_array_becomes_array() {
3204        // 对齐 PHP: 缓存非数组 → 创建 [value]
3205        let cache = make_cache();
3206
3207        // 先写入字符串(非数组)
3208        cache.set("key", "not_an_array".to_string(), None).unwrap();
3209
3210        // push 应覆盖为数组
3211        cache.push("key", "first".to_string(), None).unwrap();
3212
3213        let val: Option<Vec<String>> = cache.get("key").unwrap();
3214        assert_eq!(val, Some(vec!["first".to_string()]));
3215    }
3216
3217    // ========================================================================
3218    // 组 11:Cache facade remember(缓存击穿防护 + PHP bug 复刻)
3219    // ========================================================================
3220
3221    #[test]
3222    fn test_cache_remember_cache_miss() {
3223        // 未命中:调用 callback 并写入缓存
3224        let cache = make_cache();
3225        let counter = std::sync::Arc::new(std::sync::atomic::AtomicU32::new(0));
3226        let counter_clone = counter.clone();
3227
3228        let val: i64 = cache
3229            .remember("expensive", None, || {
3230                counter_clone.fetch_add(1, std::sync::atomic::Ordering::SeqCst) as i64 + 100
3231            })
3232            .unwrap();
3233        assert_eq!(val, 100);
3234
3235        // 第二次调用应命中缓存,callback 不被调用
3236        let val: i64 = cache
3237            .remember("expensive", None, || {
3238                counter_clone.fetch_add(1, std::sync::atomic::Ordering::SeqCst) as i64 + 200
3239            })
3240            .unwrap();
3241        assert_eq!(val, 100); // 命中缓存,仍是 100
3242
3243        // callback 只被调用一次
3244        assert_eq!(counter.load(std::sync::atomic::Ordering::SeqCst), 1);
3245    }
3246
3247    #[test]
3248    fn test_cache_remember_cache_hit_returns_cached() {
3249        let cache = make_cache();
3250        cache.set("predefined", 42i64, None).unwrap();
3251
3252        // 命中缓存,callback 不应被调用
3253        let val: i64 = cache
3254            .remember("predefined", None, || {
3255                panic!("callback should not be called on cache hit");
3256            })
3257            .unwrap();
3258        assert_eq!(val, 42);
3259    }
3260
3261    #[test]
3262    fn test_cache_remember_writes_with_ttl() {
3263        let cache = make_cache();
3264        cache
3265            .remember("key", Some(Duration::from_millis(50)), || 42i64)
3266            .unwrap();
3267
3268        // 立即读取应命中
3269        assert_eq!(cache.get::<String>("key").unwrap(), Some("42".to_string()));
3270
3271        // 等待过期
3272        std::thread::sleep(Duration::from_millis(100));
3273        assert!(cache.get::<String>("key").unwrap().is_none());
3274    }
3275
3276    #[test]
3277    fn test_cache_remember_releases_lock_on_success() {
3278        // 对齐 PHP: callback 成功后释放锁
3279        let cache = make_cache();
3280        cache.remember("key", None, || 42i64).unwrap();
3281
3282        // 锁应被释放
3283        assert!(!cache.has("key_lock").unwrap());
3284    }
3285
3286    #[test]
3287    fn test_cache_remember_releases_lock_on_panic() {
3288        // 对齐 PHP finally 块:callback panic 时也应释放锁
3289        // Rust 端:由于我们用 FnOnce() -> T(无 Result),panic 会传播
3290        // 但锁会被泄漏(因为 panic 会跳过 delete)
3291        // 这是 PHP 行为的"复刻"(PHP 也存在 try/finally 在 fatal error 时不执行)
3292        // 此测试验证正常路径下锁被释放
3293        let cache = make_cache();
3294        let _ = cache.remember("key", None, || 42i64);
3295        assert!(!cache.has("key_lock").unwrap());
3296    }
3297
3298    #[test]
3299    fn test_cache_remember_lock_has_no_ttl_php_bug() {
3300        // PHP 源码 bug 复刻:锁 key 无 TTL
3301        // 验证方式:remember 期间,锁 key 被设置为 1,且无 TTL
3302        // 由于 remember 是同步的,我们无法在 callback 中检查锁
3303        // 此测试通过代码审查确认(PHP 源码第 305 行:$this->set($lockName, 1) 无第三个参数)
3304        // 函数签名 set(&self, key, value, ttl: Option<Duration>),ttl = None 即无 TTL
3305
3306        // 此处验证锁被正确释放(间接验证锁机制正常工作)
3307        let cache = make_cache();
3308        cache.remember("key", None, || 42i64).unwrap();
3309        assert!(!cache.has("key_lock").unwrap());
3310    }
3311
3312    #[tokio::test]
3313    async fn test_cache_remember_async_cache_miss() {
3314        // 未命中:调用 async callback 并写入缓存
3315        let cache = make_cache();
3316        let counter = std::sync::Arc::new(std::sync::atomic::AtomicU32::new(0));
3317        let counter_clone = counter.clone();
3318
3319        let val: i64 = cache
3320            .remember_async("expensive_async", None, || {
3321                let counter_clone = counter_clone.clone();
3322                async move {
3323                    counter_clone.fetch_add(1, std::sync::atomic::Ordering::SeqCst) as i64 + 100
3324                }
3325            })
3326            .await
3327            .unwrap();
3328        assert_eq!(val, 100);
3329
3330        // 第二次调用应命中缓存,callback 不被调用
3331        let val: i64 = cache
3332            .remember_async("expensive_async", None, || {
3333                let counter_clone = counter_clone.clone();
3334                async move {
3335                    counter_clone.fetch_add(1, std::sync::atomic::Ordering::SeqCst) as i64 + 200
3336                }
3337            })
3338            .await
3339            .unwrap();
3340        assert_eq!(val, 100);
3341
3342        assert_eq!(counter.load(std::sync::atomic::Ordering::SeqCst), 1);
3343    }
3344
3345    #[tokio::test]
3346    async fn test_cache_remember_async_cache_hit_returns_cached() {
3347        let cache = make_cache();
3348        cache.set("predefined_async", 42i64, None).unwrap();
3349
3350        let val: i64 = cache
3351            .remember_async("predefined_async", None, || async {
3352                panic!("callback should not be called on cache hit");
3353            })
3354            .await
3355            .unwrap();
3356        assert_eq!(val, 42);
3357    }
3358
3359    #[tokio::test]
3360    async fn test_cache_remember_async_writes_with_ttl() {
3361        let cache = make_cache();
3362        cache
3363            .remember_async("key_async", Some(Duration::from_millis(50)), || async {
3364                42i64
3365            })
3366            .await
3367            .unwrap();
3368
3369        assert_eq!(
3370            cache.get::<String>("key_async").unwrap(),
3371            Some("42".to_string())
3372        );
3373
3374        tokio::time::sleep(Duration::from_millis(100)).await;
3375        assert!(cache.get::<String>("key_async").unwrap().is_none());
3376    }
3377
3378    #[tokio::test]
3379    async fn test_cache_remember_async_releases_lock_on_success() {
3380        let cache = make_cache();
3381        cache
3382            .remember_async("key_async", None, || async { 42i64 })
3383            .await
3384            .unwrap();
3385        assert!(!cache.has("key_async_lock").unwrap());
3386    }
3387
3388    #[tokio::test]
3389    async fn test_cache_remember_async_lock_has_no_ttl_php_bug() {
3390        let cache = make_cache();
3391        cache
3392            .remember_async("key_async", None, || async { 42i64 })
3393            .await
3394            .unwrap();
3395        assert!(!cache.has("key_async_lock").unwrap());
3396    }
3397
3398    // ========================================================================
3399    // 组 12:Cache facade with_store(命名 store 访问)
3400    // ========================================================================
3401
3402    #[test]
3403    fn test_cache_with_store() {
3404        let cache = Cache::new();
3405        cache.register_store("redis", Box::new(MemoryCacheDriver::new()));
3406
3407        let result = cache
3408            .with_store("redis", |driver| {
3409                driver.set_raw("key", b"value".to_vec(), None)?;
3410                driver.get_raw("key")
3411            })
3412            .unwrap();
3413
3414        assert_eq!(result, Some(b"value".to_vec()));
3415    }
3416
3417    #[test]
3418    fn test_cache_with_store_not_found() {
3419        let cache = Cache::new();
3420        let result: Result<Option<Vec<u8>>, CacheError> =
3421            cache.with_store("nonexistent", |driver| driver.get_raw("key"));
3422        assert!(matches!(result, Err(CacheError::NotFound(_))));
3423    }
3424
3425    // ========================================================================
3426    // 组 13:全局 Cache facade(default_cache / init_default_cache)
3427    // ========================================================================
3428
3429    #[test]
3430    fn test_default_cache_singleton() {
3431        let c1 = default_cache();
3432        let c2 = default_cache();
3433        // 同一个全局实例
3434        assert!(std::ptr::eq(c1, c2));
3435    }
3436
3437    // 注:不测试 init_default_cache 的副作用,因为它修改全局状态,
3438    // 会影响其他测试。全局初始化应由应用入口负责。
3439
3440    // ========================================================================
3441    // 组 14:R5 PHP 行为对齐验证(硬约束)
3442    // ========================================================================
3443
3444    #[test]
3445    fn test_r5_php_set_get_basic_alignment() {
3446        // R5: PHP Cache::set + Cache::get 基本行为对齐
3447        // PHP:
3448        //   Cache::set('name', 'Alice');
3449        //   $val = Cache::get('name');  // 'Alice'
3450        let cache = make_cache();
3451        cache.set("name", "Alice", None).unwrap();
3452        let val: String = cache.get("name").unwrap().unwrap();
3453        assert_eq!(val, "Alice");
3454    }
3455
3456    #[test]
3457    fn test_r5_php_is_numeric_short_circuit() {
3458        // R5: PHP is_numeric 短路 — 数字不经过 serialize
3459        // PHP:
3460        //   Cache::set('count', 42);
3461        //   $val = Cache::get('count');  // "42" (string, PHP bug)
3462        let cache = make_cache();
3463        cache.set("count", 42i64, None).unwrap();
3464
3465        // PHP bug 复刻:get 返回 string 而非 int
3466        let s: String = cache.get("count").unwrap().unwrap();
3467        assert_eq!(s, "42");
3468    }
3469
3470    #[test]
3471    fn test_r5_php_inc_no_serialize() {
3472        // R5: PHP inc 不经序列化层 — 直接数字操作
3473        // PHP Redis: INCRBY; File: read → +step → write
3474        let cache = make_cache();
3475        cache.set("counter", 100i64, None).unwrap();
3476        let new_val = cache.inc("counter", 50).unwrap();
3477        assert_eq!(new_val, 150);
3478
3479        // 验证存储的是数字字符串
3480        let s: String = cache.get("counter").unwrap().unwrap();
3481        assert_eq!(s, "150");
3482    }
3483
3484    #[test]
3485    fn test_r5_php_dec_no_serialize() {
3486        // R5: PHP dec 不经序列化层
3487        let cache = make_cache();
3488        cache.set("counter", 100i64, None).unwrap();
3489        let new_val = cache.dec("counter", 30).unwrap();
3490        assert_eq!(new_val, 70);
3491    }
3492
3493    #[test]
3494    fn test_r5_php_remember_lock_mechanism() {
3495        // R5: PHP remember 锁机制 — {name}_lock key + 200ms 轮询 + 5s 超时
3496        // 验证:未命中 → 调用 callback → 写入缓存 → 释放锁
3497        let cache = make_cache();
3498        let val: i64 = cache.remember("key", None, || 42).unwrap();
3499        assert_eq!(val, 42);
3500        assert_eq!(cache.get::<String>("key").unwrap(), Some("42".to_string()));
3501        // 锁应被释放
3502        assert!(!cache.has("key_lock").unwrap());
3503    }
3504
3505    #[test]
3506    fn test_r5_php_push_max_1000_array_shift() {
3507        // R5: PHP push 上限 1000 + array_shift
3508        let cache = make_cache();
3509        for i in 0..1001i64 {
3510            cache.push("list", i, None).unwrap();
3511        }
3512        let list: Vec<i64> = cache.get("list").unwrap().unwrap();
3513        assert_eq!(list.len(), 1000);
3514        assert_eq!(list[0], 1); // 0 被丢弃
3515        assert_eq!(list[999], 1000);
3516    }
3517
3518    #[test]
3519    fn test_r5_php_push_array_unique() {
3520        // R5: PHP push array_unique 去重
3521        let cache = make_cache();
3522        cache.push("list", "a".to_string(), None).unwrap();
3523        cache.push("list", "a".to_string(), None).unwrap();
3524        cache.push("list", "b".to_string(), None).unwrap();
3525        cache.push("list", "a".to_string(), None).unwrap();
3526
3527        let list: Vec<String> = cache.get("list").unwrap().unwrap();
3528        assert_eq!(list, vec!["a".to_string(), "b".to_string()]);
3529    }
3530
3531    #[test]
3532    fn test_r5_php_pull_get_then_delete() {
3533        // R5: PHP pull — get + delete
3534        let cache = make_cache();
3535        cache.set("key", "value", None).unwrap();
3536
3537        let val: Option<String> = cache.pull("key").unwrap();
3538        assert_eq!(val, Some("value".to_string()));
3539        assert!(!cache.has("key").unwrap());
3540    }
3541
3542    #[test]
3543    fn test_r5_php_delete_nonexistent_no_error() {
3544        // R5: PHP delete 不存在的 key 不报错
3545        let cache = make_cache();
3546        let result = cache.delete("nonexistent");
3547        assert!(result.is_ok());
3548    }
3549
3550    #[test]
3551    fn test_r5_php_has_ttl_expiration() {
3552        // R5: PHP has 检查 TTL 过期
3553        let cache = make_cache();
3554        cache
3555            .set("key", "value", Some(Duration::from_millis(50)))
3556            .unwrap();
3557        assert!(cache.has("key").unwrap());
3558
3559        std::thread::sleep(Duration::from_millis(100));
3560        assert!(!cache.has("key").unwrap());
3561    }
3562
3563    #[test]
3564    fn test_r5_php_clear_all_keys() {
3565        // R5: PHP clear 清空所有缓存
3566        let cache = make_cache();
3567        cache.set("key1", "value1", None).unwrap();
3568        cache.set("key2", "value2", None).unwrap();
3569        cache.set("key3", "value3", None).unwrap();
3570
3571        cache.clear().unwrap();
3572
3573        assert!(!cache.has("key1").unwrap());
3574        assert!(!cache.has("key2").unwrap());
3575        assert!(!cache.has("key3").unwrap());
3576    }
3577
3578    // ========================================================================
3579    // 组 15:PHP 源码行为对齐 — 关键 bug 复刻验证
3580    // ========================================================================
3581
3582    #[test]
3583    fn test_php_bug_unserialize_numeric_returns_string() {
3584        // PHP 源码 bug 复刻:unserialize 对 is_numeric 返回 string,而非 int
3585        // PHP 源码 think\cache\Driver::unserialize 第 623-630 行:
3586        //   public function unserialize($data)
3587        //   {
3588        //       if (is_numeric($data)) {
3589        //           return $data;  // ⚠️ 返回 string,而非 int
3590        //       }
3591        //       return unserialize($data);
3592        //   }
3593        //
3594        // Rust 端通过 CacheValue::Number + 泛型 T = String 复刻此行为
3595
3596        let cache = make_cache();
3597
3598        // 存入 i64 → is_numeric 短路 → CacheValue::Number("42")
3599        cache.set("count", 42i64, None).unwrap();
3600
3601        // 取出时返回 string,对齐 PHP bug
3602        let s: String = cache.get("count").unwrap().unwrap();
3603        assert_eq!(s, "42");
3604
3605        // 业务代码需自行 parse::<i64>()(对齐 PHP (int) Cache::get('count'))
3606        let n: i64 = s.parse().unwrap();
3607        assert_eq!(n, 42);
3608    }
3609
3610    #[test]
3611    fn test_php_bug_remember_lock_no_ttl() {
3612        // PHP 源码 bug 复刻:remember 锁 key 无 TTL
3613        // PHP 源码 think\cache\Driver::remember 第 305 行:
3614        //   $this->set($lockName, 1);  // 无第三个参数 $expire
3615        //
3616        // 验证方式:检查我们的实现也使用 ttl = None(代码审查确认)
3617        // 这里通过正常路径验证锁被释放(间接验证无 TTL 锁不会卡死)
3618
3619        let cache = make_cache();
3620        cache.remember("key", None, || 42i64).unwrap();
3621        // 锁被正常释放(无 TTL 锁在正常路径下也会被 delete)
3622        assert!(!cache.has("key_lock").unwrap());
3623    }
3624
3625    #[test]
3626    fn test_php_bug_remember_has_get_double_check() {
3627        // PHP 源码 bug 复刻:remember 中 has() + get() 双查(TOCTOU)
3628        // PHP 源码 think\cache\Driver::remember 第 295-298 行:
3629        //   if ($this->has($lockName)) {  // 第一次检查
3630        //       while ($this->has($lockName) && ...) {  // 循环中再次检查
3631        //           usleep(200000);
3632        //       }
3633        //       // ...
3634        //       $data = $this->get($name);  // 第二次检查(read)
3635        //   }
3636        //
3637        // Rust 端复刻此双查模式(代码审查确认):
3638        // 1. if self.has(&lock_key)?  // 第一次
3639        // 2. while self.has(&lock_key)?  // 循环
3640        // 3. if let Some(cached) = self.get::<T>(key)?  // 读
3641
3642        // 此测试验证正常路径下的双查行为(不触发死锁)
3643        let cache = make_cache();
3644        let val: i64 = cache.remember("key", None, || 42).unwrap();
3645        assert_eq!(val, 42);
3646    }
3647
3648    #[test]
3649    fn test_php_behavior_set_overwrite() {
3650        // PHP 行为:同 key 重复 set 覆盖旧值
3651        let cache = make_cache();
3652        cache.set("key", "first", None).unwrap();
3653        cache.set("key", "second", None).unwrap();
3654
3655        let val: String = cache.get("key").unwrap().unwrap();
3656        assert_eq!(val, "second");
3657    }
3658
3659    #[test]
3660    fn test_php_behavior_ttl_permanent() {
3661        // PHP 行为:ttl = null 永不过期
3662        let cache = make_cache();
3663        cache.set("key", "value", None).unwrap();
3664
3665        // 立即读取应命中
3666        assert!(cache.has("key").unwrap());
3667
3668        // 短暂等待后读取应仍命中(永不过期)
3669        std::thread::sleep(Duration::from_millis(50));
3670        assert!(cache.has("key").unwrap());
3671    }
3672
3673    // ========================================================================
3674    // 组 16:RedisConfig 配置(对齐 PHP think\cache\driver\Redis::$options)
3675    // ========================================================================
3676
3677    #[test]
3678    fn test_redis_config_default() {
3679        // 对齐 PHP 默认值(Redis.php 第 33-44 行)
3680        let config = RedisConfig::default();
3681        assert_eq!(config.host, "127.0.0.1");
3682        assert_eq!(config.port, 6379);
3683        assert_eq!(config.password, "");
3684        assert_eq!(config.select, 0);
3685        assert_eq!(config.timeout, Duration::ZERO);
3686        assert_eq!(config.expire, None);
3687        assert!(!config.persistent);
3688        assert_eq!(config.prefix, "");
3689        assert_eq!(config.tag_prefix, "tag:");
3690    }
3691
3692    #[test]
3693    fn test_redis_config_with_prefix() {
3694        let config = RedisConfig::with_prefix("myapp:");
3695        assert_eq!(config.prefix, "myapp:");
3696        assert_eq!(config.host, "127.0.0.1");
3697        assert_eq!(config.tag_prefix, "tag:");
3698    }
3699
3700    #[test]
3701    fn test_redis_config_with_expire() {
3702        let config = RedisConfig::with_expire(Duration::from_secs(3600));
3703        assert_eq!(config.expire, Some(Duration::from_secs(3600)));
3704        assert_eq!(config.prefix, "");
3705    }
3706
3707    // ========================================================================
3708    // 组 17:MockRedisBackend 基础 KV 操作
3709    // ========================================================================
3710
3711    #[test]
3712    fn test_mock_redis_set_get_roundtrip() {
3713        let backend = MockRedisBackend::new();
3714        backend.set("key1", b"value1".to_vec()).unwrap();
3715        let val = backend.get("key1").unwrap();
3716        assert_eq!(val, Some(b"value1".to_vec()));
3717    }
3718
3719    #[test]
3720    fn test_mock_redis_del() {
3721        let backend = MockRedisBackend::new();
3722        backend.set("key1", b"value1".to_vec()).unwrap();
3723        let removed = backend.del("key1").unwrap();
3724        assert_eq!(removed, 1);
3725        assert_eq!(backend.get("key1").unwrap(), None);
3726        // 再次删除返回 0
3727        assert_eq!(backend.del("key1").unwrap(), 0);
3728    }
3729
3730    #[test]
3731    fn test_mock_redis_exists() {
3732        let backend = MockRedisBackend::new();
3733        assert!(!backend.exists("key1").unwrap());
3734        backend.set("key1", b"value1".to_vec()).unwrap();
3735        assert!(backend.exists("key1").unwrap());
3736    }
3737
3738    #[test]
3739    fn test_mock_redis_incr_by_new_key() {
3740        // 对齐 Redis: key 不存在时初始化为 0 再 INCRBY
3741        let backend = MockRedisBackend::new();
3742        let result = backend.incr_by("counter", 5).unwrap();
3743        assert_eq!(result, 5);
3744        // 存储的是数字字符串 "5",不经 serialize
3745        let val = backend.get("counter").unwrap();
3746        assert_eq!(val, Some(b"5".to_vec()));
3747    }
3748
3749    #[test]
3750    fn test_mock_redis_incr_by_existing_key() {
3751        let backend = MockRedisBackend::new();
3752        backend.set("counter", b"10".to_vec()).unwrap();
3753        let result = backend.incr_by("counter", 5).unwrap();
3754        assert_eq!(result, 15);
3755        let val = backend.get("counter").unwrap();
3756        assert_eq!(val, Some(b"15".to_vec()));
3757    }
3758
3759    #[test]
3760    fn test_mock_redis_incr_by_non_integer_error() {
3761        // 对齐 Redis: INCRBY 对非数字值返回错误
3762        let backend = MockRedisBackend::new();
3763        backend.set("key", b"not_a_number".to_vec()).unwrap();
3764        let result = backend.incr_by("key", 1);
3765        assert!(result.is_err());
3766    }
3767
3768    #[test]
3769    fn test_mock_redis_decr_by() {
3770        let backend = MockRedisBackend::new();
3771        let result = backend.decr_by("counter", 3).unwrap();
3772        assert_eq!(result, -3);
3773    }
3774
3775    // ========================================================================
3776    // 组 18:MockRedisBackend TTL 过期
3777    // ========================================================================
3778
3779    #[test]
3780    fn test_mock_redis_set_ex_and_expire() {
3781        let backend = MockRedisBackend::new();
3782        backend
3783            .set_ex("key1", b"value1".to_vec(), Duration::from_millis(50))
3784            .unwrap();
3785        assert!(backend.get("key1").unwrap().is_some());
3786        std::thread::sleep(Duration::from_millis(80));
3787        assert_eq!(backend.get("key1").unwrap(), None);
3788    }
3789
3790    #[test]
3791    fn test_mock_redis_expired_key_exists_false() {
3792        let backend = MockRedisBackend::new();
3793        backend
3794            .set_ex("key1", b"value1".to_vec(), Duration::from_millis(50))
3795            .unwrap();
3796        assert!(backend.exists("key1").unwrap());
3797        std::thread::sleep(Duration::from_millis(80));
3798        assert!(!backend.exists("key1").unwrap());
3799    }
3800
3801    // ========================================================================
3802    // 组 19:MockRedisBackend Set 操作(对齐 Redis SADD/SMEMBERS)
3803    // ========================================================================
3804
3805    #[test]
3806    fn test_mock_redis_sadd_smembers() {
3807        let backend = MockRedisBackend::new();
3808        backend.sadd("tag:users", "user:1").unwrap();
3809        backend.sadd("tag:users", "user:2").unwrap();
3810        backend.sadd("tag:users", "user:3").unwrap();
3811        let members = backend.smembers("tag:users").unwrap();
3812        assert_eq!(members.len(), 3);
3813        assert!(members.contains(&"user:1".to_string()));
3814        assert!(members.contains(&"user:2".to_string()));
3815        assert!(members.contains(&"user:3".to_string()));
3816    }
3817
3818    #[test]
3819    fn test_mock_redis_sadd_dedup() {
3820        // 对齐 Redis SADD: 重复成员只保留一份
3821        let backend = MockRedisBackend::new();
3822        let added1 = backend.sadd("tag:users", "user:1").unwrap();
3823        assert_eq!(added1, 1);
3824        let added2 = backend.sadd("tag:users", "user:1").unwrap();
3825        assert_eq!(added2, 0);
3826        let members = backend.smembers("tag:users").unwrap();
3827        assert_eq!(members.len(), 1);
3828    }
3829
3830    #[test]
3831    fn test_mock_redis_smembers_nonexistent_key() {
3832        // 对齐 Redis: SMEMBERS 不存在的 key 返回空数组
3833        let backend = MockRedisBackend::new();
3834        let members = backend.smembers("nonexistent").unwrap();
3835        assert!(members.is_empty());
3836    }
3837
3838    // ========================================================================
3839    // 组 20:MockRedisBackend flush_db 和 del_many
3840    // ========================================================================
3841
3842    #[test]
3843    fn test_mock_redis_flush_db() {
3844        let backend = MockRedisBackend::new();
3845        backend.set("key1", b"v1".to_vec()).unwrap();
3846        backend.set("key2", b"v2".to_vec()).unwrap();
3847        backend.sadd("tag:1", "m1").unwrap();
3848        backend.flush_db().unwrap();
3849        assert_eq!(backend.get("key1").unwrap(), None);
3850        assert_eq!(backend.get("key2").unwrap(), None);
3851        assert!(backend.smembers("tag:1").unwrap().is_empty());
3852    }
3853
3854    #[test]
3855    fn test_mock_redis_del_many() {
3856        let backend = MockRedisBackend::new();
3857        backend.set("key1", b"v1".to_vec()).unwrap();
3858        backend.set("key2", b"v2".to_vec()).unwrap();
3859        backend.set("key3", b"v3".to_vec()).unwrap();
3860        let removed = backend.del_many(&["key1", "key2", "nonexistent"]).unwrap();
3861        assert_eq!(removed, 2);
3862        assert_eq!(backend.get("key1").unwrap(), None);
3863        assert_eq!(backend.get("key2").unwrap(), None);
3864        assert!(backend.get("key3").unwrap().is_some());
3865    }
3866
3867    // ========================================================================
3868    // 组 21:RedisCacheDriver 基本 API(对齐 PHP Redis 驱动)
3869    // ========================================================================
3870
3871    /// 创建带 Mock backend 的 RedisCacheDriver
3872    fn make_redis_driver() -> RedisCacheDriver {
3873        RedisCacheDriver::new(RedisConfig::default())
3874    }
3875
3876    #[test]
3877    fn test_redis_driver_set_get_roundtrip() {
3878        let driver = make_redis_driver();
3879        driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
3880        let val = driver.get_raw("key1").unwrap();
3881        assert_eq!(val, Some(b"value1".to_vec()));
3882    }
3883
3884    #[test]
3885    fn test_redis_driver_delete() {
3886        let driver = make_redis_driver();
3887        driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
3888        driver.delete("key1").unwrap();
3889        assert_eq!(driver.get_raw("key1").unwrap(), None);
3890    }
3891
3892    #[test]
3893    fn test_redis_driver_has() {
3894        let driver = make_redis_driver();
3895        assert!(!driver.has("key1").unwrap());
3896        driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
3897        assert!(driver.has("key1").unwrap());
3898    }
3899
3900    #[test]
3901    fn test_redis_driver_clear() {
3902        let driver = make_redis_driver();
3903        driver.set_raw("key1", b"v1".to_vec(), None).unwrap();
3904        driver.set_raw("key2", b"v2".to_vec(), None).unwrap();
3905        driver.clear().unwrap();
3906        assert_eq!(driver.get_raw("key1").unwrap(), None);
3907        assert_eq!(driver.get_raw("key2").unwrap(), None);
3908    }
3909
3910    #[test]
3911    fn test_redis_driver_inc_dec() {
3912        let driver = make_redis_driver();
3913        // inc 新 key(对齐 Redis INCRBY)
3914        let result = driver.inc("counter", 5).unwrap();
3915        assert_eq!(result, 5);
3916        let result = driver.inc("counter", 3).unwrap();
3917        assert_eq!(result, 8);
3918        let result = driver.dec("counter", 2).unwrap();
3919        assert_eq!(result, 6);
3920    }
3921
3922    // ========================================================================
3923    // 组 22:RedisCacheDriver key 构造(对齐 PHP getCacheKey/getTagKey)
3924    // ========================================================================
3925
3926    #[test]
3927    fn test_redis_driver_cache_key_with_prefix() {
3928        // 对齐 PHP: getCacheKey(name) = prefix + name
3929        let driver = RedisCacheDriver::new(RedisConfig::with_prefix("myapp:"));
3930        assert_eq!(driver.cache_key("user:1"), "myapp:user:1");
3931    }
3932
3933    #[test]
3934    fn test_redis_driver_cache_key_no_prefix() {
3935        let driver = RedisCacheDriver::new(RedisConfig::default());
3936        assert_eq!(driver.cache_key("user:1"), "user:1");
3937    }
3938
3939    #[test]
3940    fn test_redis_driver_tag_key_md5() {
3941        // 对齐 PHP: getTagKey(tag) = tag_prefix + md5(tag)
3942        let driver = RedisCacheDriver::new(RedisConfig::default());
3943        let tag_key = driver.tag_key("users");
3944        let expected_md5 = compute_md5("users");
3945        assert_eq!(tag_key, format!("tag:{}", expected_md5));
3946    }
3947
3948    #[test]
3949    fn test_redis_driver_tag_key_custom_prefix() {
3950        let config = RedisConfig {
3951            tag_prefix: "t:".to_string(),
3952            ..RedisConfig::default()
3953        };
3954        let driver = RedisCacheDriver::new(config);
3955        let tag_key = driver.tag_key("users");
3956        let expected_md5 = compute_md5("users");
3957        assert_eq!(tag_key, format!("t:{}", expected_md5));
3958    }
3959
3960    // ========================================================================
3961    // 组 23:RedisCacheDriver prefix 生效(对齐 PHP Redis::set/get 自动加前缀)
3962    // ========================================================================
3963
3964    #[test]
3965    fn test_redis_driver_prefix_applied_to_set() {
3966        // 对齐 PHP: set 时自动加 prefix 到 key
3967        let driver = RedisCacheDriver::new(RedisConfig::with_prefix("myapp:"));
3968        driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
3969        // 底层 backend 收到的 key 应该是 "myapp:key1"
3970        let val = driver.backend().get("myapp:key1").unwrap();
3971        assert_eq!(val, Some(b"value1".to_vec()));
3972        // 不带 prefix 的 key 应该不存在
3973        assert_eq!(driver.backend().get("key1").unwrap(), None);
3974    }
3975
3976    #[test]
3977    fn test_redis_driver_prefix_applied_to_get() {
3978        let driver = RedisCacheDriver::new(RedisConfig::with_prefix("myapp:"));
3979        driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
3980        let val = driver.get_raw("key1").unwrap();
3981        assert_eq!(val, Some(b"value1".to_vec()));
3982    }
3983
3984    #[test]
3985    fn test_redis_driver_prefix_applied_to_delete() {
3986        let driver = RedisCacheDriver::new(RedisConfig::with_prefix("myapp:"));
3987        driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
3988        driver.delete("key1").unwrap();
3989        assert_eq!(driver.backend().get("myapp:key1").unwrap(), None);
3990    }
3991
3992    #[test]
3993    fn test_redis_driver_prefix_applied_to_has() {
3994        let driver = RedisCacheDriver::new(RedisConfig::with_prefix("myapp:"));
3995        driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
3996        assert!(driver.has("key1").unwrap());
3997        assert!(driver.backend().exists("myapp:key1").unwrap());
3998    }
3999
4000    #[test]
4001    fn test_redis_driver_prefix_applied_to_inc() {
4002        let driver = RedisCacheDriver::new(RedisConfig::with_prefix("myapp:"));
4003        let result = driver.inc("counter", 5).unwrap();
4004        assert_eq!(result, 5);
4005        let val = driver.backend().get("myapp:counter").unwrap();
4006        assert_eq!(val, Some(b"5".to_vec()));
4007    }
4008
4009    // ========================================================================
4010    // 组 24:RedisCacheDriver tag 操作(对齐 PHP Redis::append/getTagItems/clearTag)
4011    // ========================================================================
4012
4013    #[test]
4014    fn test_redis_driver_append_and_get_tag_items() {
4015        // 对齐 PHP Redis::append 用 SADD
4016        let driver = make_redis_driver();
4017        driver.append("tag:users", "user:1").unwrap();
4018        driver.append("tag:users", "user:2").unwrap();
4019        driver.append("tag:users", "user:3").unwrap();
4020        let members = driver.backend().smembers("tag:users").unwrap();
4021        assert_eq!(members.len(), 3);
4022    }
4023
4024    #[test]
4025    fn test_redis_driver_get_tag_items_with_tag_key() {
4026        // 对齐 PHP: getTagItems(tag) 通过 getTagKey(tag) + getCacheKey 转换
4027        let driver = make_redis_driver();
4028        let tag_name = driver.tag_key("users");
4029        driver.append(&tag_name, "user:1").unwrap();
4030        driver.append(&tag_name, "user:2").unwrap();
4031        let members = driver.get_tag_items("users").unwrap();
4032        assert_eq!(members.len(), 2);
4033        assert!(members.contains(&"user:1".to_string()));
4034        assert!(members.contains(&"user:2".to_string()));
4035    }
4036
4037    #[test]
4038    fn test_redis_driver_clear_tag() {
4039        let driver = make_redis_driver();
4040        driver.set_raw("key1", b"v1".to_vec(), None).unwrap();
4041        driver.set_raw("key2", b"v2".to_vec(), None).unwrap();
4042        driver.clear_tag(&["key1", "key2"]).unwrap();
4043        assert_eq!(driver.get_raw("key1").unwrap(), None);
4044        assert_eq!(driver.get_raw("key2").unwrap(), None);
4045    }
4046
4047    // ========================================================================
4048    // 组 25:RedisCacheDriver TTL(对齐 PHP Redis::set 的 SETEX vs SET 行为)
4049    // ========================================================================
4050
4051    #[test]
4052    fn test_redis_driver_set_with_ttl_uses_setex() {
4053        // 对齐 PHP: expire > 0 时用 SETEX
4054        let driver = make_redis_driver();
4055        driver
4056            .set_raw("key1", b"value1".to_vec(), Some(Duration::from_millis(100)))
4057            .unwrap();
4058        assert!(driver.get_raw("key1").unwrap().is_some());
4059        std::thread::sleep(Duration::from_millis(150));
4060        assert_eq!(driver.get_raw("key1").unwrap(), None);
4061    }
4062
4063    #[test]
4064    fn test_redis_driver_set_without_ttl_uses_set() {
4065        // 对齐 PHP: expire = 0 时用 SET(永不过期)
4066        let driver = make_redis_driver();
4067        driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
4068        std::thread::sleep(Duration::from_millis(50));
4069        assert!(driver.get_raw("key1").unwrap().is_some());
4070    }
4071
4072    #[test]
4073    fn test_redis_driver_set_with_config_expire() {
4074        // 对齐 PHP: ttl = null 时用 config.expire
4075        let config = RedisConfig::with_expire(Duration::from_millis(100));
4076        let driver = RedisCacheDriver::new(config);
4077        driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
4078        assert!(driver.get_raw("key1").unwrap().is_some());
4079        std::thread::sleep(Duration::from_millis(150));
4080        assert_eq!(driver.get_raw("key1").unwrap(), None);
4081    }
4082
4083    #[test]
4084    fn test_redis_driver_set_ttl_overrides_config_expire() {
4085        // 对齐 PHP: 显式 ttl 优先于 config.expire
4086        let config = RedisConfig::with_expire(Duration::from_secs(3600));
4087        let driver = RedisCacheDriver::new(config);
4088        driver
4089            .set_raw("key1", b"value1".to_vec(), Some(Duration::from_millis(50)))
4090            .unwrap();
4091        std::thread::sleep(Duration::from_millis(80));
4092        assert_eq!(driver.get_raw("key1").unwrap(), None);
4093    }
4094
4095    // ========================================================================
4096    // 组 26:RedisCacheDriver 通过 Cache facade 使用
4097    // ========================================================================
4098
4099    #[test]
4100    fn test_redis_driver_with_cache_facade() {
4101        // 对齐 PHP: $cache = new think\Cache(); $cache->store('redis')->set(...)
4102        let cache = Cache::new();
4103        let driver = RedisCacheDriver::new(RedisConfig::default());
4104        cache.register_store("redis", Box::new(driver));
4105        cache.set_default_store("redis").unwrap();
4106        cache.set("key", "value", None).unwrap();
4107        let val: String = cache.get("key").unwrap().unwrap();
4108        assert_eq!(val, "value");
4109    }
4110
4111    #[test]
4112    fn test_redis_driver_with_cache_facade_inc() {
4113        // 通过 Cache facade 使用 Redis 驱动的 inc(不经 serialize)
4114        let cache = Cache::new();
4115        let driver = RedisCacheDriver::new(RedisConfig::default());
4116        cache.register_store("redis", Box::new(driver));
4117        cache.set_default_store("redis").unwrap();
4118        let result = cache.inc("counter", 5).unwrap();
4119        assert_eq!(result, 5);
4120        let result = cache.inc("counter", 3).unwrap();
4121        assert_eq!(result, 8);
4122    }
4123
4124    // ========================================================================
4125    // 组 27:PHP 行为对齐验证(R5 Redis 硬约束)
4126    // ========================================================================
4127
4128    #[test]
4129    fn test_php_redis_inc_not_through_serialize() {
4130        // R5-Redis-1: inc 不经 serialize(存储的是数字字符串,不是 PHP serialize 格式)
4131        // PHP Redis::inc 直接 INCRBY,File 驱动读取→加减→写回
4132        // 验证:Redis 驱动 inc 后,底层存储的是 "5"(数字字符串),
4133        //       而不是 PHP serialize 格式 "i:5;"
4134        let driver = make_redis_driver();
4135        driver.inc("counter", 5).unwrap();
4136        let val = driver.backend().get(&driver.cache_key("counter")).unwrap();
4137        assert_eq!(val, Some(b"5".to_vec())); // 数字字符串
4138        assert_ne!(val, Some(b"i:5;".to_vec())); // 不是 PHP serialize 格式
4139    }
4140
4141    #[test]
4142    fn test_php_redis_set_with_ttl_expires() {
4143        // R5-Redis-2: set 带 TTL 用 SETEX(通过 TTL 过期行为验证)
4144        let driver = make_redis_driver();
4145        driver
4146            .set_raw("key", b"value".to_vec(), Some(Duration::from_millis(50)))
4147            .unwrap();
4148        assert!(driver.get_raw("key").unwrap().is_some());
4149        std::thread::sleep(Duration::from_millis(80));
4150        assert_eq!(driver.get_raw("key").unwrap(), None);
4151    }
4152
4153    #[test]
4154    fn test_php_redis_set_without_ttl_permanent() {
4155        // R5-Redis-3: set 无 TTL 用 SET(永不过期)
4156        let driver = make_redis_driver();
4157        driver.set_raw("key", b"value".to_vec(), None).unwrap();
4158        std::thread::sleep(Duration::from_millis(50));
4159        assert!(driver.get_raw("key").unwrap().is_some());
4160    }
4161
4162    #[test]
4163    fn test_php_redis_tag_key_format() {
4164        // R5-Redis-4: tag_key = tag_prefix + md5(tag)
4165        let driver = make_redis_driver();
4166        let tag_key = driver.tag_key("users");
4167        let expected = format!("tag:{}", compute_md5("users"));
4168        assert_eq!(tag_key, expected);
4169        assert_eq!(compute_md5("users").len(), 32);
4170    }
4171
4172    #[test]
4173    fn test_php_redis_clear_uses_flushdb() {
4174        // R5-Redis-5: clear 用 FLUSHDB(清空所有 key 和 set)
4175        let driver = make_redis_driver();
4176        driver.set_raw("key1", b"v1".to_vec(), None).unwrap();
4177        driver.set_raw("key2", b"v2".to_vec(), None).unwrap();
4178        driver.append("tag:1", "m1").unwrap();
4179        driver.clear().unwrap();
4180        assert_eq!(driver.get_raw("key1").unwrap(), None);
4181        assert_eq!(driver.get_raw("key2").unwrap(), None);
4182        assert!(driver.backend().smembers("tag:1").unwrap().is_empty());
4183    }
4184
4185    #[test]
4186    fn test_php_redis_inc_returns_new_value() {
4187        // R5-Redis-6: inc 返回新值(对齐 PHP incrby 返回值)
4188        let driver = make_redis_driver();
4189        let r1 = driver.inc("c", 1).unwrap();
4190        assert_eq!(r1, 1);
4191        let r2 = driver.inc("c", 1).unwrap();
4192        assert_eq!(r2, 2);
4193        let r3 = driver.inc("c", 10).unwrap();
4194        assert_eq!(r3, 12);
4195        let r4 = driver.dec("c", 5).unwrap();
4196        assert_eq!(r4, 7);
4197    }
4198
4199    #[test]
4200    fn test_php_redis_delete_nonexistent_returns_ok() {
4201        // R5-Redis-7: delete 不存在的 key 返回 Ok
4202        let driver = make_redis_driver();
4203        driver.delete("nonexistent").unwrap();
4204    }
4205
4206    #[test]
4207    fn test_php_redis_md5_alignment() {
4208        // R5-Redis-8: md5 对齐 PHP md5() 函数
4209        // PHP: md5("hello") = "5d41402abc4b2a76b9719d911017c592"
4210        assert_eq!(compute_md5("hello"), "5d41402abc4b2a76b9719d911017c592");
4211        // PHP: md5("") = "d41d8cd98f00b204e9800998ecf8427e"
4212        assert_eq!(compute_md5(""), "d41d8cd98f00b204e9800998ecf8427e");
4213        assert_eq!(compute_md5("users").len(), 32);
4214    }
4215
4216    #[test]
4217    fn test_php_redis_append_uses_sadd() {
4218        // R5-Redis-9: append 用 SADD(Set 存储,去重)
4219        // 对比 PHP File 驱动 append 用 push(数组存储)
4220        let driver = make_redis_driver();
4221        driver.append("tag:1", "m1").unwrap();
4222        driver.append("tag:1", "m1").unwrap(); // 重复
4223        driver.append("tag:1", "m2").unwrap();
4224        let members = driver.backend().smembers("tag:1").unwrap();
4225        // SADD 去重:只有 2 个成员
4226        assert_eq!(members.len(), 2);
4227    }
4228
4229    #[test]
4230    fn test_php_redis_config_precedence_ttl() {
4231        // R5-Redis-10: TTL 优先级:显式 ttl > config.expire > None(永不过期)
4232        // 1. 显式 ttl 优先于 config.expire
4233        let config = RedisConfig::with_expire(Duration::from_secs(3600));
4234        let driver = RedisCacheDriver::new(config);
4235        driver
4236            .set_raw("key1", b"v1".to_vec(), Some(Duration::from_millis(50)))
4237            .unwrap();
4238        std::thread::sleep(Duration::from_millis(80));
4239        assert_eq!(driver.get_raw("key1").unwrap(), None); // 显式 ttl 生效
4240
4241        // 2. config.expire 优先于 None
4242        let config = RedisConfig::with_expire(Duration::from_millis(50));
4243        let driver = RedisCacheDriver::new(config);
4244        driver.set_raw("key2", b"v2".to_vec(), None).unwrap();
4245        std::thread::sleep(Duration::from_millis(80));
4246        assert_eq!(driver.get_raw("key2").unwrap(), None); // config.expire 生效
4247
4248        // 3. 都无则永不过期
4249        let driver = make_redis_driver();
4250        driver.set_raw("key3", b"v3".to_vec(), None).unwrap();
4251        std::thread::sleep(Duration::from_millis(50));
4252        assert!(driver.get_raw("key3").unwrap().is_some()); // 永不过期
4253    }
4254
4255    // ========================================================================
4256    // 组 28:MultiLevelCacheDriver 基础操作
4257    // ========================================================================
4258
4259    #[test]
4260    fn test_multi_level_driver_set_get() {
4261        let l1 = sz_orm_core::MemoryCache::new();
4262        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4263
4264        driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
4265        let val = driver.get_raw("key1").unwrap();
4266        assert_eq!(val, Some(b"value1".to_vec()));
4267    }
4268
4269    #[test]
4270    fn test_multi_level_driver_delete() {
4271        let l1 = sz_orm_core::MemoryCache::new();
4272        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4273
4274        driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
4275        driver.delete("key1").unwrap();
4276        assert_eq!(driver.get_raw("key1").unwrap(), None);
4277    }
4278
4279    #[test]
4280    fn test_multi_level_driver_has() {
4281        let l1 = sz_orm_core::MemoryCache::new();
4282        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4283
4284        assert!(!driver.has("key1").unwrap());
4285        driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
4286        assert!(driver.has("key1").unwrap());
4287    }
4288
4289    #[test]
4290    fn test_multi_level_driver_clear() {
4291        let l1 = sz_orm_core::MemoryCache::new();
4292        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4293
4294        driver.set_raw("key1", b"v1".to_vec(), None).unwrap();
4295        driver.set_raw("key2", b"v2".to_vec(), None).unwrap();
4296        driver.clear().unwrap();
4297        assert_eq!(driver.get_raw("key1").unwrap(), None);
4298        assert_eq!(driver.get_raw("key2").unwrap(), None);
4299    }
4300
4301    // ========================================================================
4302    // 组 29:MultiLevelCacheDriver 多层级联
4303    // ========================================================================
4304
4305    #[test]
4306    fn test_multi_level_two_levels_cascade_get() {
4307        // L1 空,L2 有数据 → get 应从 L2 命中并回填 L1
4308        let l1 = sz_orm_core::MemoryCache::new();
4309        let l2 = sz_orm_core::MemoryCache::new();
4310
4311        // 先在 L2 写入
4312        l2.set("key", b"from_l2".to_vec(), None).unwrap();
4313
4314        let driver = MultiLevelCacheDriver::new()
4315            .add_level(Box::new(l1.clone()))
4316            .add_level(Box::new(l2));
4317
4318        // L1 未命中,L2 命中
4319        let val = driver.get_raw("key").unwrap();
4320        assert_eq!(val, Some(b"from_l2".to_vec()));
4321
4322        // L1 应被回填
4323        let l1_val = l1.get("key").unwrap();
4324        assert_eq!(l1_val, Some(b"from_l2".to_vec()));
4325    }
4326
4327    #[test]
4328    fn test_multi_level_set_writes_all_levels() {
4329        let l1 = sz_orm_core::MemoryCache::new();
4330        let l2 = sz_orm_core::MemoryCache::new();
4331
4332        let driver = MultiLevelCacheDriver::new()
4333            .add_level(Box::new(l1.clone()))
4334            .add_level(Box::new(l2.clone()));
4335
4336        driver.set_raw("key", b"value".to_vec(), None).unwrap();
4337
4338        // 两层都应有
4339        assert_eq!(l1.get("key").unwrap(), Some(b"value".to_vec()));
4340        assert_eq!(l2.get("key").unwrap(), Some(b"value".to_vec()));
4341    }
4342
4343    #[test]
4344    fn test_multi_level_delete_removes_all_levels() {
4345        let l1 = sz_orm_core::MemoryCache::new();
4346        let l2 = sz_orm_core::MemoryCache::new();
4347
4348        let driver = MultiLevelCacheDriver::new()
4349            .add_level(Box::new(l1.clone()))
4350            .add_level(Box::new(l2.clone()));
4351
4352        driver.set_raw("key", b"value".to_vec(), None).unwrap();
4353        driver.delete("key").unwrap();
4354
4355        assert_eq!(l1.get("key").unwrap(), None);
4356        assert_eq!(l2.get("key").unwrap(), None);
4357    }
4358
4359    #[test]
4360    fn test_multi_level_l1_hit_skips_l2() {
4361        // L1 命中时不查询 L2
4362        let l1 = sz_orm_core::MemoryCache::new();
4363        let l2 = sz_orm_core::MemoryCache::new();
4364
4365        l1.set("key", b"from_l1".to_vec(), None).unwrap();
4366        l2.set("key", b"from_l2".to_vec(), None).unwrap();
4367
4368        let driver = MultiLevelCacheDriver::new()
4369            .add_level(Box::new(l1))
4370            .add_level(Box::new(l2));
4371
4372        let val = driver.get_raw("key").unwrap();
4373        assert_eq!(val, Some(b"from_l1".to_vec()));
4374    }
4375
4376    // ========================================================================
4377    // 组 30:MultiLevelCacheDriver inc/dec
4378    // ========================================================================
4379
4380    #[test]
4381    fn test_multi_level_driver_inc_initial_value() {
4382        let l1 = sz_orm_core::MemoryCache::new();
4383        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4384
4385        let new_val = driver.inc("counter", 1).unwrap();
4386        assert_eq!(new_val, 1);
4387
4388        let val = driver.get_raw("counter").unwrap();
4389        assert_eq!(val, Some(b"1".to_vec()));
4390    }
4391
4392    #[test]
4393    fn test_multi_level_driver_inc_accumulate() {
4394        let l1 = sz_orm_core::MemoryCache::new();
4395        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4396
4397        driver.inc("counter", 5).unwrap();
4398        driver.inc("counter", 3).unwrap();
4399        driver.inc("counter", 1).unwrap();
4400
4401        let val = driver.get_raw("counter").unwrap();
4402        assert_eq!(val, Some(b"9".to_vec()));
4403    }
4404
4405    #[test]
4406    fn test_multi_level_driver_dec() {
4407        let l1 = sz_orm_core::MemoryCache::new();
4408        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4409
4410        driver.set_raw("counter", b"10".to_vec(), None).unwrap();
4411        let new_val = driver.dec("counter", 3).unwrap();
4412        assert_eq!(new_val, 7);
4413
4414        let val = driver.get_raw("counter").unwrap();
4415        assert_eq!(val, Some(b"7".to_vec()));
4416    }
4417
4418    #[test]
4419    fn test_multi_level_driver_inc_preserves_ttl() {
4420        // inc/dec 应保留原 TTL
4421        let l1 = sz_orm_core::MemoryCache::new();
4422        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4423
4424        driver
4425            .set_raw("counter", b"5".to_vec(), Some(Duration::from_millis(200)))
4426            .unwrap();
4427
4428        // TTL 存在
4429        let ttl_before = driver.inner().ttl("counter").unwrap();
4430        assert!(ttl_before.is_some());
4431
4432        driver.inc("counter", 1).unwrap();
4433
4434        // TTL 应被保留
4435        let ttl_after = driver.inner().ttl("counter").unwrap();
4436        assert!(ttl_after.is_some());
4437    }
4438
4439    // ========================================================================
4440    // 组 31:MultiLevelCacheDriver TTL 过期
4441    // ========================================================================
4442
4443    #[test]
4444    fn test_multi_level_driver_ttl_expiration() {
4445        let l1 = sz_orm_core::MemoryCache::new();
4446        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4447
4448        driver
4449            .set_raw("key", b"value".to_vec(), Some(Duration::from_millis(50)))
4450            .unwrap();
4451        assert!(driver.get_raw("key").unwrap().is_some());
4452
4453        std::thread::sleep(Duration::from_millis(80));
4454        assert_eq!(driver.get_raw("key").unwrap(), None);
4455    }
4456
4457    #[test]
4458    fn test_multi_level_driver_has_checks_ttl() {
4459        let l1 = sz_orm_core::MemoryCache::new();
4460        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4461
4462        driver
4463            .set_raw("key", b"value".to_vec(), Some(Duration::from_millis(50)))
4464            .unwrap();
4465        assert!(driver.has("key").unwrap());
4466
4467        std::thread::sleep(Duration::from_millis(80));
4468        assert!(!driver.has("key").unwrap());
4469    }
4470
4471    // ========================================================================
4472    // 组 32:MultiLevelCacheDriver 通过 Cache facade 使用
4473    // ========================================================================
4474
4475    #[test]
4476    fn test_multi_level_driver_with_cache_facade() {
4477        let l1 = sz_orm_core::MemoryCache::new();
4478        let l2 = sz_orm_core::MemoryCache::new();
4479        let driver = MultiLevelCacheDriver::new()
4480            .add_level(Box::new(l1))
4481            .add_level(Box::new(l2));
4482
4483        let cache = Cache::new();
4484        cache.register_store("default", Box::new(driver));
4485
4486        cache.set("user:1", "Alice", None).unwrap();
4487        assert_eq!(
4488            cache.get::<String>("user:1").unwrap(),
4489            Some("Alice".to_string())
4490        );
4491
4492        cache.delete("user:1").unwrap();
4493        assert_eq!(cache.get::<String>("user:1").unwrap(), None);
4494    }
4495
4496    #[test]
4497    fn test_multi_level_driver_with_cache_facade_inc() {
4498        let l1 = sz_orm_core::MemoryCache::new();
4499        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4500
4501        let cache = Cache::new();
4502        cache.register_store("default", Box::new(driver));
4503
4504        cache.inc("counter", 5).unwrap();
4505        cache.inc("counter", 3).unwrap();
4506
4507        // PHP bug 复刻:inc 不经 serialize,存储为字符串 "8"
4508        // get::<String> 返回 "8"
4509        let val = cache.get::<String>("counter").unwrap();
4510        assert_eq!(val, Some("8".to_string()));
4511    }
4512
4513    // ========================================================================
4514    // 组 33:MultiLevelCacheDriver 边界情况
4515    // ========================================================================
4516
4517    #[test]
4518    fn test_multi_level_driver_empty_levels_get_returns_none() {
4519        // 无任何层级的驱动,get 返回 None(不报错)
4520        let driver = MultiLevelCacheDriver::new();
4521        assert_eq!(driver.get_raw("key").unwrap(), None);
4522    }
4523
4524    #[test]
4525    fn test_multi_level_driver_empty_levels_has_returns_false() {
4526        let driver = MultiLevelCacheDriver::new();
4527        assert!(!driver.has("key").unwrap());
4528    }
4529
4530    #[test]
4531    fn test_multi_level_driver_inc_non_numeric_value_resets_to_step() {
4532        // 非 numeric value 时,parse 失败降级为 0,再 +step
4533        let l1 = sz_orm_core::MemoryCache::new();
4534        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4535
4536        driver
4537            .set_raw("counter", b"not_a_number".to_vec(), None)
4538            .unwrap();
4539        let new_val = driver.inc("counter", 5).unwrap();
4540        assert_eq!(new_val, 5);
4541    }
4542
4543    #[test]
4544    fn test_multi_level_driver_default_impl() {
4545        // Default::default() 等价于 new()
4546        let driver = MultiLevelCacheDriver::default();
4547        assert_eq!(driver.get_raw("key").unwrap(), None);
4548    }
4549
4550    // ========================================================================
4551    // 组 34:R5 PHP 行为对齐验证(多级缓存)
4552    // ========================================================================
4553
4554    #[test]
4555    fn test_r5_multi_level_get_set_basic() {
4556        // R5: 基本 set/get 行为对齐 PHP Cache::set/get
4557        let l1 = sz_orm_core::MemoryCache::new();
4558        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4559
4560        driver.set_raw("key", b"value".to_vec(), None).unwrap();
4561        assert_eq!(driver.get_raw("key").unwrap(), Some(b"value".to_vec()));
4562    }
4563
4564    #[test]
4565    fn test_r5_multi_level_delete_nonexistent_no_error() {
4566        // R5: 删除不存在的 key 不报错
4567        let l1 = sz_orm_core::MemoryCache::new();
4568        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4569
4570        assert!(driver.delete("nonexistent").is_ok());
4571    }
4572
4573    #[test]
4574    fn test_r5_multi_level_clear_empties_all() {
4575        // R5: clear 清空所有层
4576        let l1 = sz_orm_core::MemoryCache::new();
4577        let l2 = sz_orm_core::MemoryCache::new();
4578        let driver = MultiLevelCacheDriver::new()
4579            .add_level(Box::new(l1))
4580            .add_level(Box::new(l2));
4581
4582        driver.set_raw("k1", b"v1".to_vec(), None).unwrap();
4583        driver.set_raw("k2", b"v2".to_vec(), None).unwrap();
4584        driver.clear().unwrap();
4585
4586        assert_eq!(driver.get_raw("k1").unwrap(), None);
4587        assert_eq!(driver.get_raw("k2").unwrap(), None);
4588    }
4589
4590    #[test]
4591    fn test_r5_multi_level_cascade_fill_back() {
4592        // R5: 多级查询命中后回填低层(带 TTL 保留)
4593        let l1 = sz_orm_core::MemoryCache::new();
4594        let l2 = sz_orm_core::MemoryCache::new();
4595
4596        // L2 有数据,L1 无
4597        l2.set("key", b"from_l2".to_vec(), None).unwrap();
4598
4599        let driver = MultiLevelCacheDriver::new()
4600            .add_level(Box::new(l1.clone()))
4601            .add_level(Box::new(l2));
4602
4603        // get 触发回填
4604        let val = driver.get_raw("key").unwrap();
4605        assert_eq!(val, Some(b"from_l2".to_vec()));
4606
4607        // L1 应被回填
4608        assert_eq!(l1.get("key").unwrap(), Some(b"from_l2".to_vec()));
4609    }
4610
4611    // ========================================================================
4612    // 测试组 35: CacheDriver tag trait 默认实现(MemoryCacheDriver)
4613    // ========================================================================
4614
4615    #[test]
4616    fn test_tag_get_cache_key_default_no_prefix() {
4617        // 默认 get_cache_key 不应用前缀
4618        let driver = MemoryCacheDriver::new();
4619        assert_eq!(driver.get_cache_key("user:1"), "user:1");
4620        assert_eq!(driver.get_cache_key("hello"), "hello");
4621    }
4622
4623    #[test]
4624    fn test_tag_get_tag_key_default_format() {
4625        // 默认 get_tag_key = "tag:" + md5(tag)
4626        let driver = MemoryCacheDriver::new();
4627        let tag_key = driver.get_tag_key("user");
4628        // md5("user") = "ee11cbb19052e40b07aac0ca060c23ee"
4629        assert_eq!(tag_key, "tag:ee11cbb19052e40b07aac0ca060c23ee");
4630    }
4631
4632    #[test]
4633    fn test_tag_append_creates_new_tag_set() {
4634        // tag_append 首次调用创建空数组 + 追加
4635        let driver = MemoryCacheDriver::new();
4636        driver.tag_append("tag:abc123", "user:1").unwrap();
4637        // 直接验证存储(tag_append 第一个参数是 tag_key,存储在 get_cache_key(tag_key) 位置)
4638        let storage_key = "tag:abc123"; // get_cache_key("tag:abc123") = "tag:abc123" (no prefix)
4639        let raw = driver.get_raw(storage_key).unwrap();
4640        let stored: Vec<String> = serde_json::from_slice(&raw.unwrap()).unwrap();
4641        assert_eq!(stored, vec!["user:1"]);
4642    }
4643
4644    #[test]
4645    fn test_tag_append_appends_to_existing() {
4646        let driver = MemoryCacheDriver::new();
4647        driver.tag_append("tag:abc", "key1").unwrap();
4648        driver.tag_append("tag:abc", "key2").unwrap();
4649        let storage_key = "tag:abc";
4650        let raw = driver.get_raw(storage_key).unwrap();
4651        let stored: Vec<String> = serde_json::from_slice(&raw.unwrap()).unwrap();
4652        assert_eq!(stored, vec!["key1", "key2"]);
4653    }
4654
4655    #[test]
4656    fn test_tag_append_dedup() {
4657        // 对齐 PHP array_unique:重复值只保留首次出现
4658        let driver = MemoryCacheDriver::new();
4659        driver.tag_append("tag:abc", "key1").unwrap();
4660        driver.tag_append("tag:abc", "key1").unwrap(); // 重复
4661        let storage_key = "tag:abc";
4662        let raw = driver.get_raw(storage_key).unwrap();
4663        let stored: Vec<String> = serde_json::from_slice(&raw.unwrap()).unwrap();
4664        assert_eq!(stored, vec!["key1"]);
4665    }
4666
4667    #[test]
4668    fn test_tag_append_max_1000_cap() {
4669        // 对齐 PHP: count > 1000 时 array_shift(FIFO 丢弃最旧)
4670        let driver = MemoryCacheDriver::new();
4671        for i in 0..1001i64 {
4672            driver.tag_append("tag:abc", &format!("key{}", i)).unwrap();
4673        }
4674        let storage_key = "tag:abc";
4675        let raw = driver.get_raw(storage_key).unwrap();
4676        let stored: Vec<String> = serde_json::from_slice(&raw.unwrap()).unwrap();
4677        // 上限 1000,丢弃 key0
4678        assert_eq!(stored.len(), 1000);
4679        assert!(!stored.contains(&"key0".to_string()));
4680        assert!(stored.contains(&"key1".to_string()));
4681        assert!(stored.contains(&"key1000".to_string()));
4682    }
4683
4684    #[test]
4685    fn test_tag_items_empty_returns_empty() {
4686        let driver = MemoryCacheDriver::new();
4687        let items = driver.tag_items("nonexistent_tag").unwrap();
4688        assert!(items.is_empty());
4689    }
4690
4691    #[test]
4692    fn test_tag_items_returns_stored_keys() {
4693        let driver = MemoryCacheDriver::new();
4694        // tag_items 内部计算 get_tag_key("mytag") = "tag:" + md5("mytag")
4695        let tag_key = driver.get_tag_key("mytag");
4696        driver.tag_append(&tag_key, "key1").unwrap();
4697        driver.tag_append(&tag_key, "key2").unwrap();
4698        let items = driver.tag_items("mytag").unwrap();
4699        assert_eq!(items, vec!["key1", "key2"]);
4700    }
4701
4702    #[test]
4703    fn test_tag_clear_deletes_keys() {
4704        let driver = MemoryCacheDriver::new();
4705        // 写入两个缓存 key
4706        driver.set_raw("key1", b"v1".to_vec(), None).unwrap();
4707        driver.set_raw("key2", b"v2".to_vec(), None).unwrap();
4708        // tag_clear 删除这些 key(无前缀驱动,key = name)
4709        driver
4710            .tag_clear(&["key1".to_string(), "key2".to_string()])
4711            .unwrap();
4712        assert!(!driver.has("key1").unwrap());
4713        assert!(!driver.has("key2").unwrap());
4714    }
4715
4716    #[test]
4717    fn test_tag_clear_empty_no_error() {
4718        let driver = MemoryCacheDriver::new();
4719        // 空列表不报错
4720        driver.tag_clear(&[]).unwrap();
4721    }
4722
4723    // ========================================================================
4724    // 测试组 36: RedisCacheDriver tag trait 重写
4725    // ========================================================================
4726
4727    #[test]
4728    fn test_redis_tag_get_cache_key_with_prefix() {
4729        let config = RedisConfig {
4730            prefix: "myapp:".to_string(),
4731            ..RedisConfig::default()
4732        };
4733        let driver = RedisCacheDriver::new(config);
4734        assert_eq!(driver.get_cache_key("user:1"), "myapp:user:1");
4735    }
4736
4737    #[test]
4738    fn test_redis_tag_get_tag_key_with_tag_prefix() {
4739        let config = RedisConfig {
4740            tag_prefix: "tag:".to_string(),
4741            ..RedisConfig::default()
4742        };
4743        let driver = RedisCacheDriver::new(config);
4744        let tag_key = driver.get_tag_key("user");
4745        // md5("user") = "ee11cbb19052e40b07aac0ca060c23ee"
4746        assert_eq!(tag_key, "tag:ee11cbb19052e40b07aac0ca060c23ee");
4747    }
4748
4749    #[test]
4750    fn test_redis_tag_get_tag_key_custom_prefix() {
4751        let config = RedisConfig {
4752            tag_prefix: "t:".to_string(),
4753            ..RedisConfig::default()
4754        };
4755        let driver = RedisCacheDriver::new(config);
4756        let tag_key = driver.get_tag_key("user");
4757        assert_eq!(tag_key, "t:ee11cbb19052e40b07aac0ca060c23ee");
4758    }
4759
4760    #[test]
4761    fn test_redis_tag_append_uses_sadd() {
4762        // Redis tag_append 用 sAdd(Set 语义),而非 push(Array 语义)
4763        let driver = RedisCacheDriver::new(RedisConfig::default());
4764        let tag_key = driver.get_tag_key("mytag");
4765        driver.tag_append(&tag_key, "key1").unwrap();
4766        driver.tag_append(&tag_key, "key2").unwrap();
4767        driver.tag_append(&tag_key, "key1").unwrap(); // 重复(Set 自动去重)
4768        let items = driver.tag_items("mytag").unwrap();
4769        // Set 去重,只有 2 个元素
4770        assert_eq!(items.len(), 2);
4771        assert!(items.contains(&"key1".to_string()));
4772        assert!(items.contains(&"key2".to_string()));
4773    }
4774
4775    #[test]
4776    fn test_redis_tag_items_uses_smembers() {
4777        let driver = RedisCacheDriver::new(RedisConfig::default());
4778        let tag_key = driver.get_tag_key("mytag");
4779        driver.tag_append(&tag_key, "a").unwrap();
4780        driver.tag_append(&tag_key, "b").unwrap();
4781        driver.tag_append(&tag_key, "c").unwrap();
4782        let items = driver.tag_items("mytag").unwrap();
4783        assert_eq!(items.len(), 3);
4784    }
4785
4786    #[test]
4787    fn test_redis_tag_clear_does_not_double_prefix() {
4788        // tag_clear 接收已前缀化的 key,不得再次应用 getCacheKey
4789        let config = RedisConfig {
4790            prefix: "app:".to_string(),
4791            ..RedisConfig::default()
4792        };
4793        let driver = RedisCacheDriver::new(config);
4794        // 写入缓存(set_raw 应用前缀 → "app:key1")
4795        driver.set_raw("key1", b"v1".to_vec(), None).unwrap();
4796        // tag_items 返回 "app:key1"(已前缀化)
4797        let tag_key = driver.get_tag_key("mytag");
4798        driver.tag_append(&tag_key, "app:key1").unwrap();
4799        let items = driver.tag_items("mytag").unwrap();
4800        assert_eq!(items, vec!["app:key1"]);
4801        // tag_clear 应删除 "app:key1"(raw del),不是 "app:app:key1"
4802        driver.tag_clear(&items).unwrap();
4803        assert!(!driver.has("key1").unwrap());
4804    }
4805
4806    #[test]
4807    fn test_redis_tag_clear_empty_no_error() {
4808        let driver = RedisCacheDriver::new(RedisConfig::default());
4809        driver.tag_clear(&[]).unwrap();
4810    }
4811
4812    // ========================================================================
4813    // 测试组 37: TagSet with MemoryCacheDriver
4814    // ========================================================================
4815
4816    #[test]
4817    fn test_tagset_set_stores_value_and_appends_tag() {
4818        let cache = Cache::new();
4819        cache.register_default(MemoryCacheDriver::new());
4820
4821        // TagSet::set = cache.set + append
4822        cache.tag("user").set("user:1", "Alice", None).unwrap();
4823
4824        // 缓存值已写入
4825        assert_eq!(
4826            cache.get::<String>("user:1").unwrap(),
4827            Some("Alice".to_string())
4828        );
4829
4830        // 标签已记录 key
4831        let mgr = cache.manager.read();
4832        let driver = mgr.default_store().unwrap();
4833        let items = driver.tag_items("user").unwrap();
4834        assert_eq!(items, vec!["user:1"]);
4835    }
4836
4837    #[test]
4838    fn test_tagset_set_multiple_keys_same_tag() {
4839        let cache = Cache::new();
4840        cache.register_default(MemoryCacheDriver::new());
4841
4842        cache.tag("user").set("user:1", "Alice", None).unwrap();
4843        cache.tag("user").set("user:2", "Bob", None).unwrap();
4844        cache.tag("user").set("user:3", "Carol", None).unwrap();
4845
4846        let mgr = cache.manager.read();
4847        let driver = mgr.default_store().unwrap();
4848        let items = driver.tag_items("user").unwrap();
4849        assert_eq!(items, vec!["user:1", "user:2", "user:3"]);
4850    }
4851
4852    #[test]
4853    fn test_tagset_clear_deletes_all_tagged_keys() {
4854        let cache = Cache::new();
4855        cache.register_default(MemoryCacheDriver::new());
4856
4857        cache.tag("user").set("user:1", "Alice", None).unwrap();
4858        cache.tag("user").set("user:2", "Bob", None).unwrap();
4859        cache.tag("user").set("user:3", "Carol", None).unwrap();
4860
4861        // clear 删除所有标签下的缓存
4862        cache.tag("user").clear().unwrap();
4863
4864        assert!(cache.get::<String>("user:1").unwrap().is_none());
4865        assert!(cache.get::<String>("user:2").unwrap().is_none());
4866        assert!(cache.get::<String>("user:3").unwrap().is_none());
4867    }
4868
4869    #[test]
4870    fn test_tagset_clear_deletes_tag_key() {
4871        let cache = Cache::new();
4872        cache.register_default(MemoryCacheDriver::new());
4873
4874        cache.tag("user").set("user:1", "Alice", None).unwrap();
4875
4876        // 验证 tag key 存在
4877        let mgr = cache.manager.read();
4878        let driver = mgr.default_store().unwrap();
4879        let tag_key = driver.get_tag_key("user");
4880        assert!(driver.has(&tag_key).unwrap());
4881        drop(mgr);
4882
4883        cache.tag("user").clear().unwrap();
4884
4885        // tag key 本身也被删除
4886        let mgr = cache.manager.read();
4887        let driver = mgr.default_store().unwrap();
4888        assert!(!driver.has(&tag_key).unwrap());
4889    }
4890
4891    #[test]
4892    fn test_tagset_clear_empty_tag_no_error() {
4893        let cache = Cache::new();
4894        cache.register_default(MemoryCacheDriver::new());
4895
4896        // 没有写入任何缓存,clear 不报错
4897        cache.tag("empty").clear().unwrap();
4898    }
4899
4900    #[test]
4901    fn test_tagset_append_adds_key_to_tag() {
4902        let cache = Cache::new();
4903        cache.register_default(MemoryCacheDriver::new());
4904
4905        // 先写入缓存(不经 TagSet)
4906        cache.set("user:1", "Alice", None).unwrap();
4907        // 然后手动 append 到标签
4908        cache.tag("user").append("user:1").unwrap();
4909
4910        let mgr = cache.manager.read();
4911        let driver = mgr.default_store().unwrap();
4912        let items = driver.tag_items("user").unwrap();
4913        assert_eq!(items, vec!["user:1"]);
4914    }
4915
4916    #[test]
4917    fn test_tagset_many_tags_single_key() {
4918        let cache = Cache::new();
4919        cache.register_default(MemoryCacheDriver::new());
4920
4921        // 多标签:key 同时属于 user 和 admin
4922        cache
4923            .tag_many(&["user", "admin"])
4924            .set("key1", "val", None)
4925            .unwrap();
4926
4927        // 两个标签都应包含 key1
4928        let mgr = cache.manager.read();
4929        let driver = mgr.default_store().unwrap();
4930        let user_items = driver.tag_items("user").unwrap();
4931        let admin_items = driver.tag_items("admin").unwrap();
4932        assert_eq!(user_items, vec!["key1"]);
4933        assert_eq!(admin_items, vec!["key1"]);
4934    }
4935
4936    #[test]
4937    fn test_tagset_many_tags_clear_one() {
4938        let cache = Cache::new();
4939        cache.register_default(MemoryCacheDriver::new());
4940
4941        cache
4942            .tag_many(&["user", "admin"])
4943            .set("key1", "val", None)
4944            .unwrap();
4945
4946        // 清除 user 标签
4947        cache.tag("user").clear().unwrap();
4948
4949        // key1 被删除
4950        assert!(cache.get::<String>("key1").unwrap().is_none());
4951
4952        // admin 标签的 tag_items 仍有 key1(但 key1 已被删除)
4953        // 这是 PHP 的行为:clear 只清除 tag 下记录的 key,不清理其他 tag 的记录
4954        let mgr = cache.manager.read();
4955        let driver = mgr.default_store().unwrap();
4956        let admin_items = driver.tag_items("admin").unwrap();
4957        assert_eq!(admin_items, vec!["key1"]); // 记录仍在,但 key1 已被删
4958                                               // user 的 tag key 被删除
4959        let user_tag_key = driver.get_tag_key("user");
4960        assert!(!driver.has(&user_tag_key).unwrap());
4961    }
4962
4963    #[test]
4964    fn test_tagset_tags_getter() {
4965        let cache = Cache::new();
4966        let ts = cache.tag_many(&["a", "b", "c"]);
4967        assert_eq!(ts.tags(), &["a", "b", "c"]);
4968    }
4969
4970    // ========================================================================
4971    // 测试组 38: TagSet with RedisCacheDriver
4972    // ========================================================================
4973
4974    #[test]
4975    fn test_redis_tagset_set_stores_value_and_appends_tag() {
4976        let cache = Cache::new();
4977        let driver = RedisCacheDriver::new(RedisConfig::default());
4978        cache.register_store("redis", Box::new(driver));
4979
4980        cache.tag("user").set("user:1", "Alice", None).unwrap();
4981
4982        // 缓存值已写入
4983        assert_eq!(
4984            cache.get::<String>("user:1").unwrap(),
4985            Some("Alice".to_string())
4986        );
4987
4988        // 标签已记录 key(Redis Set 语义)
4989        let mgr = cache.manager.read();
4990        let driver = mgr.default_store().unwrap();
4991        let items = driver.tag_items("user").unwrap();
4992        assert_eq!(items, vec!["user:1"]);
4993    }
4994
4995    #[test]
4996    fn test_redis_tagset_set_with_prefix() {
4997        let cache = Cache::new();
4998        let config = RedisConfig {
4999            prefix: "app:".to_string(),
5000            ..RedisConfig::default()
5001        };
5002        let driver = RedisCacheDriver::new(config);
5003        cache.register_store("redis", Box::new(driver));
5004
5005        cache.tag("user").set("user:1", "Alice", None).unwrap();
5006
5007        // 验证 tag_items 返回已前缀化的 key
5008        let mgr = cache.manager.read();
5009        let driver = mgr.default_store().unwrap();
5010        let items = driver.tag_items("user").unwrap();
5011        assert_eq!(items, vec!["app:user:1"]);
5012    }
5013
5014    #[test]
5015    fn test_redis_tagset_clear_deletes_all_tagged_keys() {
5016        let cache = Cache::new();
5017        let driver = RedisCacheDriver::new(RedisConfig::default());
5018        cache.register_store("redis", Box::new(driver));
5019
5020        cache.tag("user").set("user:1", "Alice", None).unwrap();
5021        cache.tag("user").set("user:2", "Bob", None).unwrap();
5022        cache.tag("user").set("user:3", "Carol", None).unwrap();
5023
5024        cache.tag("user").clear().unwrap();
5025
5026        assert!(cache.get::<String>("user:1").unwrap().is_none());
5027        assert!(cache.get::<String>("user:2").unwrap().is_none());
5028        assert!(cache.get::<String>("user:3").unwrap().is_none());
5029    }
5030
5031    #[test]
5032    fn test_redis_tagset_clear_deletes_tag_key() {
5033        let cache = Cache::new();
5034        let driver = RedisCacheDriver::new(RedisConfig::default());
5035        cache.register_store("redis", Box::new(driver));
5036
5037        cache.tag("user").set("user:1", "Alice", None).unwrap();
5038
5039        let mgr = cache.manager.read();
5040        let driver = mgr.default_store().unwrap();
5041        let tag_key = driver.get_tag_key("user");
5042        // tag key 存在于 Redis backend
5043        assert!(driver.has(&tag_key).unwrap());
5044        drop(mgr);
5045
5046        cache.tag("user").clear().unwrap();
5047
5048        let mgr = cache.manager.read();
5049        let driver = mgr.default_store().unwrap();
5050        assert!(!driver.has(&tag_key).unwrap());
5051    }
5052
5053    #[test]
5054    fn test_redis_tagset_many_tags() {
5055        let cache = Cache::new();
5056        let driver = RedisCacheDriver::new(RedisConfig::default());
5057        cache.register_store("redis", Box::new(driver));
5058
5059        cache
5060            .tag_many(&["user", "admin"])
5061            .set("key1", "val", None)
5062            .unwrap();
5063
5064        let mgr = cache.manager.read();
5065        let driver = mgr.default_store().unwrap();
5066        let user_items = driver.tag_items("user").unwrap();
5067        let admin_items = driver.tag_items("admin").unwrap();
5068        assert_eq!(user_items, vec!["key1"]);
5069        assert_eq!(admin_items, vec!["key1"]);
5070    }
5071
5072    // ========================================================================
5073    // 测试组 39: R5 PHP 行为对齐
5074    // ========================================================================
5075
5076    #[test]
5077    fn test_r5_php_tag_set_then_clear() {
5078        // R5: 对齐 PHP Cache::tag('user')->set() + Cache::tag('user')->clear()
5079        let cache = Cache::new();
5080        cache.register_default(MemoryCacheDriver::new());
5081
5082        cache.tag("user").set("u1", "Alice", None).unwrap();
5083        cache.tag("user").set("u2", "Bob", None).unwrap();
5084
5085        // 非标签缓存不受影响
5086        cache.set("other", "data", None).unwrap();
5087
5088        cache.tag("user").clear().unwrap();
5089
5090        // 标签缓存被清除
5091        assert!(cache.get::<String>("u1").unwrap().is_none());
5092        assert!(cache.get::<String>("u2").unwrap().is_none());
5093        // 非标签缓存保留
5094        assert_eq!(
5095            cache.get::<String>("other").unwrap(),
5096            Some("data".to_string())
5097        );
5098    }
5099
5100    #[test]
5101    fn test_r5_php_tag_multiple_tags_clear() {
5102        // R5: 对齐 PHP 多标签场景
5103        let cache = Cache::new();
5104        cache.register_default(MemoryCacheDriver::new());
5105
5106        // key1 属于 user + admin
5107        cache
5108            .tag_many(&["user", "admin"])
5109            .set("key1", "v1", None)
5110            .unwrap();
5111        // key2 仅属于 user
5112        cache.tag("user").set("key2", "v2", None).unwrap();
5113
5114        // 清除 user 标签(key1 和 key2 都被删除)
5115        cache.tag("user").clear().unwrap();
5116
5117        assert!(cache.get::<String>("key1").unwrap().is_none());
5118        assert!(cache.get::<String>("key2").unwrap().is_none());
5119    }
5120
5121    #[test]
5122    fn test_r5_php_tag_get_cache_key_prefix() {
5123        // R5: 对齐 PHP getCacheKey — MemoryCacheDriver 无前缀
5124        let cache = Cache::new();
5125        cache.register_default(MemoryCacheDriver::new());
5126        let mgr = cache.manager.read();
5127        let driver = mgr.default_store().unwrap();
5128        assert_eq!(driver.get_cache_key("test"), "test");
5129    }
5130
5131    #[test]
5132    fn test_r5_php_tag_get_tag_key_md5() {
5133        // R5: 对齐 PHP getTagKey — tag_prefix + md5(tag)
5134        let cache = Cache::new();
5135        cache.register_default(MemoryCacheDriver::new());
5136        let mgr = cache.manager.read();
5137        let driver = mgr.default_store().unwrap();
5138        // md5("hello") = "5d41402abc4b2a76b9719d911017c592"
5139        assert_eq!(
5140            driver.get_tag_key("hello"),
5141            "tag:5d41402abc4b2a76b9719d911017c592"
5142        );
5143    }
5144
5145    #[test]
5146    fn test_r5_php_tag_push_max_1000_array_shift() {
5147        // R5: 对齐 PHP push 上限 1000 + array_shift(FIFO 丢弃最旧)
5148        let driver = MemoryCacheDriver::new();
5149        for i in 0..1005i64 {
5150            driver.tag_append("tag:test", &format!("key{}", i)).unwrap();
5151        }
5152        let storage_key = "tag:test";
5153        let raw = driver.get_raw(storage_key).unwrap();
5154        let stored: Vec<String> = serde_json::from_slice(&raw.unwrap()).unwrap();
5155        // 上限 1000
5156        assert_eq!(stored.len(), 1000);
5157        // key0~key4 被丢弃
5158        assert!(!stored.contains(&"key0".to_string()));
5159        assert!(!stored.contains(&"key4".to_string()));
5160        // key5~key1004 保留
5161        assert!(stored.contains(&"key5".to_string()));
5162        assert!(stored.contains(&"key1004".to_string()));
5163    }
5164
5165    #[test]
5166    fn test_r5_php_tag_push_array_unique() {
5167        // R5: 对齐 PHP array_unique — 去重保留首次出现
5168        let driver = MemoryCacheDriver::new();
5169        driver.tag_append("tag:u", "a").unwrap();
5170        driver.tag_append("tag:u", "b").unwrap();
5171        driver.tag_append("tag:u", "a").unwrap(); // 重复
5172        driver.tag_append("tag:u", "c").unwrap();
5173        driver.tag_append("tag:u", "b").unwrap(); // 重复
5174
5175        let storage_key = "tag:u";
5176        let raw = driver.get_raw(storage_key).unwrap();
5177        let stored: Vec<String> = serde_json::from_slice(&raw.unwrap()).unwrap();
5178        // 去重后 a, b, c(保留首次出现顺序)
5179        assert_eq!(stored, vec!["a", "b", "c"]);
5180    }
5181
5182    #[test]
5183    fn test_r5_php_tag_singleton_equivalent() {
5184        // R5: 对齐 PHP tag() 单例 — 多次调用行为一致
5185        let cache = Cache::new();
5186        cache.register_default(MemoryCacheDriver::new());
5187
5188        // 第一次调用 tag("user")
5189        cache.tag("user").set("u1", "Alice", None).unwrap();
5190        // 第二次调用 tag("user") — PHP 返回同一个 TagSet 单例
5191        cache.tag("user").set("u2", "Bob", None).unwrap();
5192
5193        // 两次 set 的 key 都在同一标签下
5194        let mgr = cache.manager.read();
5195        let driver = mgr.default_store().unwrap();
5196        let items = driver.tag_items("user").unwrap();
5197        assert_eq!(items, vec!["u1", "u2"]);
5198
5199        // clear 一次清除所有
5200        cache.tag("user").clear().unwrap();
5201        assert!(cache.get::<String>("u1").unwrap().is_none());
5202        assert!(cache.get::<String>("u2").unwrap().is_none());
5203    }
5204
5205    #[test]
5206    fn test_r5_php_tag_clear_then_set_again() {
5207        // R5: clear 后可以重新 set
5208        let cache = Cache::new();
5209        cache.register_default(MemoryCacheDriver::new());
5210
5211        cache.tag("user").set("u1", "Alice", None).unwrap();
5212        cache.tag("user").clear().unwrap();
5213        assert!(cache.get::<String>("u1").unwrap().is_none());
5214
5215        // 重新 set
5216        cache.tag("user").set("u1", "Alice2", None).unwrap();
5217        assert_eq!(
5218            cache.get::<String>("u1").unwrap(),
5219            Some("Alice2".to_string())
5220        );
5221
5222        // tag items 只包含重新 set 后的 key
5223        let mgr = cache.manager.read();
5224        let driver = mgr.default_store().unwrap();
5225        let items = driver.tag_items("user").unwrap();
5226        assert_eq!(items, vec!["u1"]);
5227    }
5228
5229    #[test]
5230    fn test_r5_php_tag_redis_set_then_clear() {
5231        // R5: Redis 驱动 tag set + clear 对齐 PHP
5232        let cache = Cache::new();
5233        let driver = RedisCacheDriver::new(RedisConfig::default());
5234        cache.register_store("redis", Box::new(driver));
5235
5236        cache.tag("article").set("a:1", "Hello", None).unwrap();
5237        cache.tag("article").set("a:2", "World", None).unwrap();
5238        cache.set("untagged", "data", None).unwrap();
5239
5240        cache.tag("article").clear().unwrap();
5241
5242        assert!(cache.get::<String>("a:1").unwrap().is_none());
5243        assert!(cache.get::<String>("a:2").unwrap().is_none());
5244        // 非标签缓存保留
5245        assert_eq!(
5246            cache.get::<String>("untagged").unwrap(),
5247            Some("data".to_string())
5248        );
5249    }
5250
5251    #[test]
5252    fn test_r5_php_tag_redis_with_prefix() {
5253        // R5: Redis 带前缀的 tag 行为对齐 PHP
5254        let cache = Cache::new();
5255        let config = RedisConfig {
5256            prefix: "myapp:".to_string(),
5257            tag_prefix: "tag:".to_string(),
5258            ..RedisConfig::default()
5259        };
5260        let driver = RedisCacheDriver::new(config);
5261        cache.register_store("redis", Box::new(driver));
5262
5263        cache.tag("user").set("u1", "Alice", None).unwrap();
5264
5265        // 验证 tag_items 返回已前缀化的 key
5266        let mgr = cache.manager.read();
5267        let driver = mgr.default_store().unwrap();
5268        let items = driver.tag_items("user").unwrap();
5269        assert_eq!(items, vec!["myapp:u1"]);
5270
5271        // clear 正确删除
5272        drop(mgr);
5273        cache.tag("user").clear().unwrap();
5274        assert!(cache.get::<String>("u1").unwrap().is_none());
5275    }
5276
5277    #[test]
5278    fn test_r5_php_tag_different_tags_isolation() {
5279        // R5: 不同标签之间互不影响
5280        let cache = Cache::new();
5281        cache.register_default(MemoryCacheDriver::new());
5282
5283        cache.tag("user").set("u1", "Alice", None).unwrap();
5284        cache.tag("article").set("a1", "Hello", None).unwrap();
5285
5286        // 清除 user 不影响 article
5287        cache.tag("user").clear().unwrap();
5288
5289        assert!(cache.get::<String>("u1").unwrap().is_none());
5290        assert_eq!(
5291            cache.get::<String>("a1").unwrap(),
5292            Some("Hello".to_string())
5293        );
5294    }
5295
5296    #[test]
5297    fn test_r5_php_tag_set_with_ttl() {
5298        // R5: TagSet::set 支持 TTL
5299        let cache = Cache::new();
5300        cache.register_default(MemoryCacheDriver::new());
5301
5302        cache
5303            .tag("user")
5304            .set("u1", "Alice", Some(Duration::from_millis(50)))
5305            .unwrap();
5306
5307        assert_eq!(
5308            cache.get::<String>("u1").unwrap(),
5309            Some("Alice".to_string())
5310        );
5311
5312        std::thread::sleep(Duration::from_millis(60));
5313        assert!(cache.get::<String>("u1").unwrap().is_none());
5314    }
5315
5316    // ========================================================================
5317    // 测试组 54: delete_many 批量删除(对齐 PHP deleteMultiple)
5318    // ========================================================================
5319
5320    #[test]
5321    fn test_delete_many_multiple_keys() {
5322        // 批量删除多个 key
5323        let cache = Cache::new();
5324        cache.register_default(MemoryCacheDriver::new());
5325        cache.set("k1", "v1", None).unwrap();
5326        cache.set("k2", "v2", None).unwrap();
5327        cache.set("k3", "v3", None).unwrap();
5328
5329        cache.delete_many(&["k1", "k2", "k3"]).unwrap();
5330
5331        assert!(cache.get::<String>("k1").unwrap().is_none());
5332        assert!(cache.get::<String>("k2").unwrap().is_none());
5333        assert!(cache.get::<String>("k3").unwrap().is_none());
5334    }
5335
5336    #[test]
5337    fn test_delete_many_nonexistent_keys_ok() {
5338        // 删除不存在的 key 不失败(修正 PHP File::delete bug)
5339        let cache = Cache::new();
5340        cache.register_default(MemoryCacheDriver::new());
5341        cache.set("exists", "v", None).unwrap();
5342
5343        // 不存在的 key + 存在的 key 混合
5344        let result = cache.delete_many(&["exists", "nonexistent"]);
5345        assert!(result.is_ok());
5346    }
5347
5348    #[test]
5349    fn test_delete_many_empty_slice() {
5350        // 空切片返回 Ok
5351        let cache = Cache::new();
5352        cache.register_default(MemoryCacheDriver::new());
5353        let result = cache.delete_many(&[]);
5354        assert!(result.is_ok());
5355    }
5356
5357    #[test]
5358    fn test_delete_many_partial_delete_before_failure() {
5359        // delete_many 逐个删除,部分成功后失败(对齐 PHP 语义)
5360        // 注:MemoryCacheDriver 不会失败,这里验证空切片+有值切片行为一致性
5361        let cache = Cache::new();
5362        cache.register_default(MemoryCacheDriver::new());
5363        cache.set("a", "1", None).unwrap();
5364        cache.set("b", "2", None).unwrap();
5365
5366        cache.delete_many(&["a", "b"]).unwrap();
5367        assert!(cache.get::<String>("a").unwrap().is_none());
5368        assert!(cache.get::<String>("b").unwrap().is_none());
5369    }
5370
5371    // ========================================================================
5372    // 测试组 55: invalidate_after_write 写后失效
5373    // ========================================================================
5374
5375    #[test]
5376    fn test_invalidate_after_write_basic() {
5377        // 写后失效基本语义:delete 后下次 get 返回 None
5378        let cache = Cache::new();
5379        cache.register_default(MemoryCacheDriver::new());
5380        cache.set("user:1", "Alice", None).unwrap();
5381        assert_eq!(
5382            cache.get::<String>("user:1").unwrap(),
5383            Some("Alice".to_string())
5384        );
5385
5386        // 写操作后失效缓存
5387        cache.invalidate_after_write(&["user:1"]).unwrap();
5388        assert!(cache.get::<String>("user:1").unwrap().is_none());
5389    }
5390
5391    #[test]
5392    fn test_invalidate_after_write_multiple_keys() {
5393        // 多 key 失效(对齐业务场景 4:一次写操作失效多类缓存)
5394        let cache = Cache::new();
5395        cache.register_default(MemoryCacheDriver::new());
5396        cache.set("sdp_category_tree", "t1", None).unwrap();
5397        cache.set("sdp_category_select", "s1", None).unwrap();
5398        cache.set("sdp_category_child", "c1", None).unwrap();
5399
5400        cache
5401            .invalidate_after_write(&[
5402                "sdp_category_tree",
5403                "sdp_category_select",
5404                "sdp_category_child",
5405            ])
5406            .unwrap();
5407
5408        assert!(cache.get::<String>("sdp_category_tree").unwrap().is_none());
5409        assert!(cache
5410            .get::<String>("sdp_category_select")
5411            .unwrap()
5412            .is_none());
5413        assert!(cache.get::<String>("sdp_category_child").unwrap().is_none());
5414    }
5415
5416    #[test]
5417    fn test_invalidate_after_write_fire_and_forget() {
5418        // fire and forget 模式(对齐 PHP 业务代码不检查返回值)
5419        let cache = Cache::new();
5420        cache.register_default(MemoryCacheDriver::new());
5421        cache.set("clerk:1", "data", None).unwrap();
5422
5423        // 用 let _ = 忽略返回值(对齐 PHP fire and forget)
5424        let _ = cache.invalidate_after_write(&["clerk:1"]);
5425        assert!(cache.get::<String>("clerk:1").unwrap().is_none());
5426    }
5427
5428    // ========================================================================
5429    // 测试组 56: refresh 先删后读强制刷新
5430    // ========================================================================
5431
5432    #[test]
5433    fn test_refresh_force_update() {
5434        // 先删后读强制刷新:delete → fetcher → set
5435        let cache = Cache::new();
5436        cache.register_default(MemoryCacheDriver::new());
5437        cache.set("store:1", "old_data", None).unwrap();
5438
5439        let result: String = cache
5440            .refresh("store:1", None, || Ok("new_data".to_string()))
5441            .unwrap();
5442
5443        assert_eq!(result, "new_data");
5444        assert_eq!(
5445            cache.get::<String>("store:1").unwrap(),
5446            Some("new_data".to_string())
5447        );
5448    }
5449
5450    #[test]
5451    fn test_refresh_fetcher_error_no_write() {
5452        // fetcher 失败时不写入缓存(错误传播)
5453        let cache = Cache::new();
5454        cache.register_default(MemoryCacheDriver::new());
5455        cache.set("key", "original", None).unwrap();
5456
5457        // fetcher 返回错误
5458        let result: Result<String, CacheError> = cache.refresh("key", None, || {
5459            Err(CacheError::SerializationError("fetch failed".to_string()))
5460        });
5461
5462        assert!(result.is_err());
5463        // delete 已执行,缓存被清空
5464        assert!(cache.get::<String>("key").unwrap().is_none());
5465    }
5466
5467    #[test]
5468    fn test_refresh_ttl_propagation() {
5469        // TTL 透传到 set
5470        let cache = Cache::new();
5471        cache.register_default(MemoryCacheDriver::new());
5472
5473        let _result: String = cache
5474            .refresh("ttl_key", Some(Duration::from_millis(50)), || {
5475                Ok("value".to_string())
5476            })
5477            .unwrap();
5478
5479        // 立即可读
5480        assert_eq!(
5481            cache.get::<String>("ttl_key").unwrap(),
5482            Some("value".to_string())
5483        );
5484
5485        // 等待过期
5486        std::thread::sleep(Duration::from_millis(60));
5487        assert!(cache.get::<String>("ttl_key").unwrap().is_none());
5488    }
5489
5490    #[test]
5491    fn test_refresh_returns_fetcher_value() {
5492        // refresh 返回 fetcher 的值(不是缓存中的旧值)
5493        // 注:用 String 类型避免 PHP unserialize numeric → string bug 影响
5494        let cache = Cache::new();
5495        cache.register_default(MemoryCacheDriver::new());
5496        cache.set("counter", "old_value", None).unwrap();
5497
5498        let result: String = cache
5499            .refresh("counter", None, || Ok("new_value".to_string()))
5500            .unwrap();
5501        assert_eq!(result, "new_value");
5502        assert_eq!(
5503            cache.get::<String>("counter").unwrap(),
5504            Some("new_value".to_string())
5505        );
5506    }
5507
5508    // ========================================================================
5509    // 测试组 57: R5 PHP 行为对齐(缓存失效策略)
5510    // ========================================================================
5511
5512    #[test]
5513    fn test_r5_php_delete_multiple_semantics() {
5514        // R5: 对齐 PHP Driver::deleteMultiple 逐个删除语义
5515        // PHP: foreach ($keys as $key) { $result = $this->delete($key); if (false === $result) return false; }
5516        let cache = Cache::new();
5517        cache.register_default(MemoryCacheDriver::new());
5518        cache.set("a", "1", None).unwrap();
5519        cache.set("b", "2", None).unwrap();
5520        cache.set("c", "3", None).unwrap();
5521
5522        // 对齐 PHP deleteMultiple(['a', 'b', 'c'])
5523        let result = cache.delete_many(&["a", "b", "c"]);
5524        assert!(result.is_ok()); // PHP 返回 true
5525
5526        // 所有 key 已删除
5527        assert!(cache.get::<String>("a").unwrap().is_none());
5528        assert!(cache.get::<String>("b").unwrap().is_none());
5529        assert!(cache.get::<String>("c").unwrap().is_none());
5530    }
5531
5532    #[test]
5533    fn test_r5_php_invalidate_after_write_pattern() {
5534        // R5: 对齐 PHP 业务场景 1(事务内写后失效)
5535        // PHP: if($this->save($data)){ Cache::delete('foodCashierClerkAll_' . $data['cashier_id']); $this->commit(); }
5536        let cache = Cache::new();
5537        cache.register_default(MemoryCacheDriver::new());
5538
5539        // 模拟业务:先写入缓存数据
5540        cache
5541            .set("foodCashierClerkAll_1", vec!["clerk1"], None)
5542            .unwrap();
5543
5544        // 模拟写操作(如数据库 save)后失效缓存
5545        let write_success = true;
5546        if write_success {
5547            cache
5548                .invalidate_after_write(&["foodCashierClerkAll_1"])
5549                .unwrap();
5550        }
5551
5552        // 缓存已失效,下次 get 返回 None(触发回源)
5553        assert!(cache
5554            .get::<Vec<String>>("foodCashierClerkAll_1")
5555            .unwrap()
5556            .is_none());
5557    }
5558
5559    #[test]
5560    fn test_r5_php_refresh_pattern() {
5561        // R5: 对齐 PHP 业务场景 2(先删后读强制刷新)
5562        // PHP: Cache::delete($cacheKey); $info = Cache::get($cacheKey); if(!$info){ $info = 回源; Cache::set(...); }
5563        let cache = Cache::new();
5564        cache.register_default(MemoryCacheDriver::new());
5565
5566        // 初始缓存数据
5567        cache
5568            .set("wmall_store_info_1", "old_store_data", None)
5569            .unwrap();
5570
5571        // 强制刷新(对齐 PHP info() 方法)
5572        let result: String = cache
5573            .refresh("wmall_store_info_1", None, || {
5574                // 模拟回源查询
5575                Ok("fresh_store_data".to_string())
5576            })
5577            .unwrap();
5578
5579        assert_eq!(result, "fresh_store_data");
5580        assert_eq!(
5581            cache.get::<String>("wmall_store_info_1").unwrap(),
5582            Some("fresh_store_data".to_string())
5583        );
5584    }
5585
5586    // ========================================================================
5587    // 测试组 58: fetch_singleflight 单飞模式(防止缓存击穿)
5588    // ========================================================================
5589
5590    #[test]
5591    fn test_fetch_singleflight_cache_hit() {
5592        // 缓存命中时不调用 fetcher
5593        let cache = Cache::new();
5594        cache.register_default(MemoryCacheDriver::new());
5595        cache.set("hot", "cached_value", None).unwrap();
5596
5597        let called = Arc::new(Mutex::new(false));
5598        let called_clone = called.clone();
5599        let result: String = cache
5600            .fetch_singleflight("hot", None, || {
5601                *called_clone.lock() = true;
5602                Ok("fetcher_value".to_string())
5603            })
5604            .unwrap();
5605
5606        assert_eq!(result, "cached_value");
5607        assert!(!*called.lock(), "fetcher 不应被调用(缓存命中)");
5608    }
5609
5610    #[test]
5611    fn test_fetch_singleflight_cache_miss_invokes_fetcher() {
5612        // 缓存未命中时调用 fetcher 并写入缓存
5613        let cache = Cache::new();
5614        cache.register_default(MemoryCacheDriver::new());
5615
5616        let result: String = cache
5617            .fetch_singleflight("miss_key", None, || Ok("fetched".to_string()))
5618            .unwrap();
5619
5620        assert_eq!(result, "fetched");
5621        assert_eq!(
5622            cache.get::<String>("miss_key").unwrap(),
5623            Some("fetched".to_string())
5624        );
5625    }
5626
5627    #[test]
5628    fn test_fetch_singleflight_concurrent_only_one_fetcher_call() {
5629        // 并发场景:同一 key 多线程请求,fetcher 只调用一次
5630        let cache = Arc::new(Cache::new());
5631        cache.register_default(MemoryCacheDriver::new());
5632
5633        let fetcher_call_count = Arc::new(Mutex::new(0u32));
5634        let barrier = Arc::new(Barrier::new(4));
5635        let results = Arc::new(Mutex::new(Vec::<String>::new()));
5636
5637        let mut handles = Vec::new();
5638        for _ in 0..4 {
5639            let cache_clone = Arc::clone(&cache);
5640            let count_clone = Arc::clone(&fetcher_call_count);
5641            let barrier_clone = Arc::clone(&barrier);
5642            let results_clone = Arc::clone(&results);
5643
5644            handles.push(std::thread::spawn(move || {
5645                // 所有线程同步开始,确保并发
5646                barrier_clone.wait();
5647
5648                let value: String = cache_clone
5649                    .fetch_singleflight("concurrent_key", None, || {
5650                        // 模拟慢回源
5651                        std::thread::sleep(Duration::from_millis(50));
5652                        let mut count = count_clone.lock();
5653                        *count += 1;
5654                        Ok(format!("fetched_{}", *count))
5655                    })
5656                    .unwrap();
5657
5658                results_clone.lock().push(value);
5659            }));
5660        }
5661
5662        for handle in handles {
5663            handle.join().unwrap();
5664        }
5665
5666        // fetcher 应该只被调用一次(singleflight 互斥)
5667        assert_eq!(
5668            *fetcher_call_count.lock(),
5669            1,
5670            "fetcher 应只调用一次(singleflight)"
5671        );
5672
5673        // 所有线程应该拿到相同的值
5674        let results = results.lock();
5675        assert_eq!(results.len(), 4);
5676        for value in results.iter() {
5677            assert_eq!(value, "fetched_1");
5678        }
5679    }
5680
5681    #[test]
5682    fn test_fetch_singleflight_fetcher_error_propagates() {
5683        // fetcher 失败时错误传播,不写入缓存
5684        let cache = Cache::new();
5685        cache.register_default(MemoryCacheDriver::new());
5686
5687        let result: Result<String, CacheError> = cache.fetch_singleflight("err_key", None, || {
5688            Err(CacheError::SerializationError("fetcher failed".to_string()))
5689        });
5690
5691        assert!(result.is_err());
5692        assert!(cache.get::<String>("err_key").unwrap().is_none());
5693    }
5694
5695    // ========================================================================
5696    // 测试组 59: set_with_jitter 随机抖动 TTL(防止缓存雪崩)
5697    // ========================================================================
5698
5699    #[test]
5700    fn test_set_with_jitter_basic() {
5701        // 基本功能:写入缓存且可读
5702        let cache = Cache::new();
5703        cache.register_default(MemoryCacheDriver::new());
5704
5705        cache
5706            .set_with_jitter(
5707                "jitter_key",
5708                "value",
5709                Some(Duration::from_secs(60)),
5710                Duration::from_secs(10),
5711            )
5712            .unwrap();
5713
5714        assert_eq!(
5715            cache.get::<String>("jitter_key").unwrap(),
5716            Some("value".to_string())
5717        );
5718    }
5719
5720    #[test]
5721    fn test_set_with_jitter_zero_jitter_equivalent_to_set() {
5722        // jitter = 0 时等价于 set
5723        let cache = Cache::new();
5724        cache.register_default(MemoryCacheDriver::new());
5725
5726        cache
5727            .set_with_jitter(
5728                "no_jitter",
5729                "value",
5730                Some(Duration::from_secs(60)),
5731                Duration::ZERO,
5732            )
5733            .unwrap();
5734
5735        assert_eq!(
5736            cache.get::<String>("no_jitter").unwrap(),
5737            Some("value".to_string())
5738        );
5739    }
5740
5741    #[test]
5742    fn test_set_with_jitter_none_ttl_no_jitter() {
5743        // ttl = None 时等价于永久缓存,jitter 被忽略
5744        let cache = Cache::new();
5745        cache.register_default(MemoryCacheDriver::new());
5746
5747        cache
5748            .set_with_jitter("permanent", "value", None, Duration::from_secs(10))
5749            .unwrap();
5750
5751        assert_eq!(
5752            cache.get::<String>("permanent").unwrap(),
5753            Some("value".to_string())
5754        );
5755    }
5756
5757    #[test]
5758    fn test_set_with_jitter_ttl_in_expected_range() {
5759        // TTL 在 [ttl, ttl + jitter] 范围内(通过过期时间验证)
5760        let cache = Cache::new();
5761        cache.register_default(MemoryCacheDriver::new());
5762
5763        let base_ttl = Duration::from_millis(50);
5764        let jitter = Duration::from_millis(100);
5765
5766        cache
5767            .set_with_jitter("range_key", "value", Some(base_ttl), jitter)
5768            .unwrap();
5769
5770        // 立即可读
5771        assert!(cache.get::<String>("range_key").unwrap().is_some());
5772
5773        // 等待 base_ttl + jitter + 缓冲后应已过期
5774        std::thread::sleep(base_ttl + jitter + Duration::from_millis(20));
5775        assert!(
5776            cache.get::<String>("range_key").unwrap().is_none(),
5777            "TTL 应在 [{:?}, {:?}] 范围内,已过期",
5778            base_ttl,
5779            base_ttl + jitter
5780        );
5781    }
5782
5783    // ========================================================================
5784    // 测试组 60: fetch_with_protection 组合防护(singleflight + jitter)
5785    // ========================================================================
5786
5787    #[test]
5788    fn test_fetch_with_protection_cache_hit() {
5789        // 缓存命中时不调用 fetcher
5790        let cache = Cache::new();
5791        cache.register_default(MemoryCacheDriver::new());
5792        cache.set("protected", "cached", None).unwrap();
5793
5794        let called = Arc::new(Mutex::new(false));
5795        let called_clone = called.clone();
5796        let result: String = cache
5797            .fetch_with_protection(
5798                "protected",
5799                Some(Duration::from_secs(60)),
5800                Duration::from_secs(10),
5801                || {
5802                    *called_clone.lock() = true;
5803                    Ok("fetched".to_string())
5804                },
5805            )
5806            .unwrap();
5807
5808        assert_eq!(result, "cached");
5809        assert!(!*called.lock());
5810    }
5811
5812    #[test]
5813    fn test_fetch_with_protection_cache_miss_invokes_fetcher() {
5814        // 缓存未命中时调用 fetcher 并写入缓存
5815        let cache = Cache::new();
5816        cache.register_default(MemoryCacheDriver::new());
5817
5818        let result: String = cache
5819            .fetch_with_protection(
5820                "miss_protected",
5821                Some(Duration::from_secs(60)),
5822                Duration::from_secs(10),
5823                || Ok("fetched_protected".to_string()),
5824            )
5825            .unwrap();
5826
5827        assert_eq!(result, "fetched_protected");
5828        assert_eq!(
5829            cache.get::<String>("miss_protected").unwrap(),
5830            Some("fetched_protected".to_string())
5831        );
5832    }
5833
5834    #[test]
5835    fn test_fetch_with_protection_concurrent_single_flight() {
5836        // 并发场景:组合防护下 fetcher 只调用一次
5837        let cache = Arc::new(Cache::new());
5838        cache.register_default(MemoryCacheDriver::new());
5839
5840        let fetcher_call_count = Arc::new(Mutex::new(0u32));
5841        let barrier = Arc::new(Barrier::new(4));
5842        let results = Arc::new(Mutex::new(Vec::<String>::new()));
5843
5844        let mut handles = Vec::new();
5845        for _ in 0..4 {
5846            let cache_clone = Arc::clone(&cache);
5847            let count_clone = Arc::clone(&fetcher_call_count);
5848            let barrier_clone = Arc::clone(&barrier);
5849            let results_clone = Arc::clone(&results);
5850
5851            handles.push(std::thread::spawn(move || {
5852                barrier_clone.wait();
5853
5854                let value: String = cache_clone
5855                    .fetch_with_protection(
5856                        "concurrent_protected",
5857                        Some(Duration::from_secs(60)),
5858                        Duration::from_secs(10),
5859                        || {
5860                            std::thread::sleep(Duration::from_millis(50));
5861                            let mut count = count_clone.lock();
5862                            *count += 1;
5863                            Ok(format!("value_{}", *count))
5864                        },
5865                    )
5866                    .unwrap();
5867
5868                results_clone.lock().push(value);
5869            }));
5870        }
5871
5872        for handle in handles {
5873            handle.join().unwrap();
5874        }
5875
5876        assert_eq!(*fetcher_call_count.lock(), 1, "fetcher 应只调用一次");
5877
5878        let results = results.lock();
5879        assert_eq!(results.len(), 4);
5880        for value in results.iter() {
5881            assert_eq!(value, "value_1");
5882        }
5883    }
5884
5885    #[test]
5886    fn test_fetch_with_protection_fetcher_error_propagates() {
5887        // fetcher 失败时错误传播,不写入缓存
5888        let cache = Cache::new();
5889        cache.register_default(MemoryCacheDriver::new());
5890
5891        let result: Result<String, CacheError> = cache.fetch_with_protection(
5892            "err_protected",
5893            Some(Duration::from_secs(60)),
5894            Duration::from_secs(10),
5895            || Err(CacheError::SerializationError("failed".to_string())),
5896        );
5897
5898        assert!(result.is_err());
5899        assert!(cache.get::<String>("err_protected").unwrap().is_none());
5900    }
5901
5902    // ========================================================================
5903    // 测试组 61: R5 PHP 行为对比(缓存防护)
5904    // ========================================================================
5905
5906    #[test]
5907    fn test_r5_php_remember_lock_vs_rust_singleflight() {
5908        // R5: 对比 PHP remember 的"锁雏形"与 Rust singleflight 的正确实现
5909        // PHP remember 用 $this->set($name.'_lock', true) 非原子加锁(缺陷)
5910        // Rust singleflight 用 parking_lot::Mutex::lock() 原子互斥(正确)
5911        let cache = Arc::new(Cache::new());
5912        cache.register_default(MemoryCacheDriver::new());
5913
5914        let call_count = Arc::new(Mutex::new(0u32));
5915        let barrier = Arc::new(Barrier::new(3));
5916        let results = Arc::new(Mutex::new(Vec::<String>::new()));
5917
5918        let mut handles = Vec::new();
5919        for _ in 0..3 {
5920            let cache_clone = Arc::clone(&cache);
5921            let count_clone = Arc::clone(&call_count);
5922            let barrier_clone = Arc::clone(&barrier);
5923            let results_clone = Arc::clone(&results);
5924
5925            handles.push(std::thread::spawn(move || {
5926                barrier_clone.wait();
5927
5928                let value: String = cache_clone
5929                    .fetch_singleflight("r5_compare_key", None, || {
5930                        std::thread::sleep(Duration::from_millis(30));
5931                        let mut count = count_clone.lock();
5932                        *count += 1;
5933                        Ok(format!("v_{}", *count))
5934                    })
5935                    .unwrap();
5936
5937                results_clone.lock().push(value);
5938            }));
5939        }
5940
5941        for handle in handles {
5942            handle.join().unwrap();
5943        }
5944
5945        // Rust singleflight:fetcher 只调用一次(对齐"正确互斥"语义)
5946        assert_eq!(
5947            *call_count.lock(),
5948            1,
5949            "Rust singleflight fetcher 应只调用一次"
5950        );
5951
5952        // 所有线程拿到相同值
5953        let results = results.lock();
5954        assert_eq!(results.len(), 3);
5955        for value in results.iter() {
5956            assert_eq!(value, "v_1");
5957        }
5958    }
5959
5960    #[test]
5961    fn test_r5_php_no_jitter_vs_rust_jitter() {
5962        // R5: 对比 PHP 无 TTL 抖动与 Rust 有 TTL 抖动
5963        // PHP getExpireTime 不做 TTL 抖动(缺陷,会雪崩)
5964        // Rust set_with_jitter 在 [ttl, ttl + jitter] 范围内随机(正确,防雪崩)
5965        let cache = Cache::new();
5966        cache.register_default(MemoryCacheDriver::new());
5967
5968        // 多次设置相同 TTL + jitter,验证实际 TTL 不同(随机性)
5969        let mut ttl_samples = Vec::new();
5970        for i in 0..10 {
5971            let key = format!("jitter_sample_{}", i);
5972            cache
5973                .set_with_jitter(
5974                    &key,
5975                    "value",
5976                    Some(Duration::from_secs(60)),
5977                    Duration::from_secs(10),
5978                )
5979                .unwrap();
5980
5981            // 通过 MemoryCacheDriver 内部 TTL 验证随机性
5982            // 注:这里只验证缓存写入成功,实际 TTL 随机性通过统计方法验证
5983            let _ = cache.get::<String>(&key).unwrap();
5984            ttl_samples.push(key);
5985        }
5986
5987        // 验证所有 key 都写入成功
5988        for key in &ttl_samples {
5989            assert_eq!(
5990                cache.get::<String>(key).unwrap(),
5991                Some("value".to_string()),
5992                "所有带抖动 TTL 的 key 都应写入成功"
5993            );
5994        }
5995    }
5996
5997    #[test]
5998    fn test_r5_php_remember_no_double_check_vs_rust_double_check() {
5999        // R5: 对比 PHP remember 无 double-check 与 Rust singleflight 有 double-check
6000        // PHP remember 获取锁后直接回源,不再次检查缓存(缺陷)
6001        // Rust singleflight 获取锁后 double-check 缓存(优化,其他线程可能已回源完成)
6002        let cache = Cache::new();
6003        cache.register_default(MemoryCacheDriver::new());
6004
6005        // 先写入缓存
6006        cache.set("double_check_key", "pre_cached", None).unwrap();
6007
6008        // 调用 fetch_singleflight,应直接命中缓存(不调用 fetcher)
6009        let called = Arc::new(Mutex::new(false));
6010        let called_clone = called.clone();
6011        let result: String = cache
6012            .fetch_singleflight("double_check_key", None, || {
6013                *called_clone.lock() = true;
6014                Ok("fetched".to_string())
6015            })
6016            .unwrap();
6017
6018        // 应返回预缓存的值,fetcher 不被调用
6019        assert_eq!(result, "pre_cached");
6020        assert!(
6021            !*called.lock(),
6022            "double-check 应命中预缓存,fetcher 不被调用"
6023        );
6024    }
6025}