Skip to main content

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