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(Debug, 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}
1802
1803impl Default for RedisConfig {
1804    fn default() -> Self {
1805        Self {
1806            host: "127.0.0.1".to_string(),
1807            port: 6379,
1808            password: String::new(),
1809            select: 0,
1810            timeout: Duration::ZERO,
1811            expire: None,
1812            persistent: false,
1813            prefix: String::new(),
1814            tag_prefix: "tag:".to_string(),
1815        }
1816    }
1817}
1818
1819impl RedisConfig {
1820    /// 创建带前缀的配置(便捷方法)
1821    pub fn with_prefix(prefix: impl Into<String>) -> Self {
1822        Self {
1823            prefix: prefix.into(),
1824            ..Default::default()
1825        }
1826    }
1827
1828    /// 创建带默认 TTL 的配置(便捷方法)
1829    pub fn with_expire(expire: Duration) -> Self {
1830        Self {
1831            expire: Some(expire),
1832            ..Default::default()
1833        }
1834    }
1835}
1836
1837/// Redis 后端 trait(抽象 Redis 命令)
1838///
1839/// 由于 Rust 端不强制依赖 `redis` crate,本 trait 抽象 Redis 命令,
1840/// 允许应用层注入真实 Redis backend(如 `redis::Connection` 包装)。
1841///
1842/// ## 默认实现
1843///
1844/// `MockRedisBackend` 用 `HashMap` 模拟 Redis 行为,用于测试和开发环境。
1845///
1846/// ## 命令映射
1847///
1848/// | Trait 方法  | Redis 命令 | PHP phpredis 调用                  |
1849/// |------------|-----------|-----------------------------------|
1850/// | `get`      | GET       | `$handler->get($key)`             |
1851/// | `set`      | SET       | `$handler->set($key, $value)`     |
1852/// | `set_ex`   | SETEX     | `$handler->setex($key, $ttl, $v)` |
1853/// | `del`      | DEL       | `$handler->del($key)`             |
1854/// | `del_many` | DEL ...   | `$handler->del($keys)`            |
1855/// | `exists`   | EXISTS    | `$handler->exists($key)`          |
1856/// | `incr_by`  | INCRBY    | `$handler->incrby($key, $step)`   |
1857/// | `decr_by`  | DECRBY    | `$handler->decrby($key, $step)`   |
1858/// | `flush_db` | FLUSHDB   | `$handler->flushDB()`             |
1859/// | `sadd`     | SADD      | `$handler->sAdd($key, $value)`    |
1860/// | `smembers` | SMEMBERS  | `$handler->sMembers($key)`        |
1861pub trait RedisBackend: Send + Sync {
1862    /// GET 命令
1863    fn get(&self, key: &str) -> Result<Option<Vec<u8>>, CacheError>;
1864    /// SET 命令(无 TTL)
1865    fn set(&self, key: &str, value: Vec<u8>) -> Result<(), CacheError>;
1866    /// SETEX 命令(带 TTL)
1867    fn set_ex(&self, key: &str, value: Vec<u8>, ttl: Duration) -> Result<(), CacheError>;
1868    /// DEL 命令(单个 key),返回删除数量
1869    fn del(&self, key: &str) -> Result<i64, CacheError>;
1870    /// DEL 命令(批量),返回删除数量
1871    fn del_many(&self, keys: &[&str]) -> Result<i64, CacheError>;
1872    /// EXISTS 命令
1873    fn exists(&self, key: &str) -> Result<bool, CacheError>;
1874    /// INCRBY 命令(key 不存在时 Redis 初始化为 0 再 INCRBY)
1875    fn incr_by(&self, key: &str, step: i64) -> Result<i64, CacheError>;
1876    /// DECRBY 命令
1877    fn decr_by(&self, key: &str, step: i64) -> Result<i64, CacheError>;
1878    /// FLUSHDB 命令(清空当前 db)
1879    fn flush_db(&self) -> Result<(), CacheError>;
1880    /// SADD 命令(向 Set 添加成员)
1881    fn sadd(&self, key: &str, member: &str) -> Result<i64, CacheError>;
1882    /// SMEMBERS 命令(返回 Set 全部成员)
1883    fn smembers(&self, key: &str) -> Result<Vec<String>, CacheError>;
1884}
1885
1886/// Mock Redis 后端(用 HashMap 模拟 Redis 行为)
1887///
1888/// 用于测试和开发环境,不需要真实 Redis 服务器。
1889///
1890/// ## 模拟行为
1891///
1892/// - KV 存储:`HashMap<String, (Vec<u8>, Option<Instant>)>` — value + expires_at
1893/// - Set 存储:`HashMap<String, HashSet<String>>`
1894/// - TTL 过期:`get`/`exists`/`incr_by`/`decr_by` 时检查过期
1895/// - INCRBY:key 不存在时初始化为 0,非数字时返回错误(对齐 Redis 行为)
1896pub struct MockRedisBackend {
1897    /// KV 存储:key → (value, expires_at)
1898    kv: parking_lot::RwLock<MockRedisKv>,
1899    /// Set 存储:key → members
1900    sets: parking_lot::RwLock<MockRedisSets>,
1901}
1902
1903/// Mock Redis KV 存储类型(key → (value, expires_at))
1904type MockRedisKv = HashMap<String, (Vec<u8>, Option<Instant>)>;
1905
1906/// Mock Redis Set 存储类型(key → members)
1907type MockRedisSets = HashMap<String, HashSet<String>>;
1908
1909impl Default for MockRedisBackend {
1910    fn default() -> Self {
1911        Self::new()
1912    }
1913}
1914
1915impl MockRedisBackend {
1916    /// 创建新的 Mock Redis 后端
1917    pub fn new() -> Self {
1918        Self {
1919            kv: parking_lot::RwLock::new(HashMap::new()),
1920            sets: parking_lot::RwLock::new(HashMap::new()),
1921        }
1922    }
1923
1924    /// 检查 key 是否已过期(内部辅助,不删除)
1925    fn is_expired(kv: &MockRedisKv, key: &str) -> bool {
1926        if let Some((_, Some(expires_at))) = kv.get(key) {
1927            return *expires_at <= Instant::now();
1928        }
1929        false
1930    }
1931}
1932
1933impl RedisBackend for MockRedisBackend {
1934    fn get(&self, key: &str) -> Result<Option<Vec<u8>>, CacheError> {
1935        let kv = self.kv.read();
1936        if Self::is_expired(&kv, key) {
1937            return Ok(None);
1938        }
1939        Ok(kv.get(key).map(|(v, _)| v.clone()))
1940    }
1941
1942    fn set(&self, key: &str, value: Vec<u8>) -> Result<(), CacheError> {
1943        let mut kv = self.kv.write();
1944        kv.insert(key.to_string(), (value, None));
1945        Ok(())
1946    }
1947
1948    fn set_ex(&self, key: &str, value: Vec<u8>, ttl: Duration) -> Result<(), CacheError> {
1949        let mut kv = self.kv.write();
1950        let expires_at = Some(Instant::now() + ttl);
1951        kv.insert(key.to_string(), (value, expires_at));
1952        Ok(())
1953    }
1954
1955    fn del(&self, key: &str) -> Result<i64, CacheError> {
1956        let mut kv = self.kv.write();
1957        let removed = kv.remove(key).is_some() as i64;
1958        // 同时清理 Set(Redis DEL 会删除所有类型)
1959        let mut sets = self.sets.write();
1960        if sets.remove(key).is_some() && removed == 0 {
1961            return Ok(1);
1962        }
1963        Ok(removed)
1964    }
1965
1966    fn del_many(&self, keys: &[&str]) -> Result<i64, CacheError> {
1967        let mut count = 0i64;
1968        for key in keys {
1969            count += self.del(key)?;
1970        }
1971        Ok(count)
1972    }
1973
1974    fn exists(&self, key: &str) -> Result<bool, CacheError> {
1975        let kv = self.kv.read();
1976        if Self::is_expired(&kv, key) {
1977            return Ok(false);
1978        }
1979        if kv.contains_key(key) {
1980            return Ok(true);
1981        }
1982        let sets = self.sets.read();
1983        Ok(sets.contains_key(key))
1984    }
1985
1986    fn incr_by(&self, key: &str, step: i64) -> Result<i64, CacheError> {
1987        let mut kv = self.kv.write();
1988        // 检查过期:过期则视为不存在
1989        if Self::is_expired(&kv, key) {
1990            kv.remove(key);
1991        }
1992        let current = match kv.get(key) {
1993            Some((bytes, _)) => {
1994                let s = std::str::from_utf8(bytes)
1995                    .map_err(|e| CacheError::DeserializationError(e.to_string()))?;
1996                s.parse::<i64>().map_err(|e| {
1997                    CacheError::Internal(format!("INCRBY failed: '{}' is not an integer: {}", s, e))
1998                })?
1999            }
2000            None => 0, // Redis 对不存在的 key 初始化为 0
2001        };
2002        let new_value = current + step;
2003        kv.insert(key.to_string(), (new_value.to_string().into_bytes(), None));
2004        Ok(new_value)
2005    }
2006
2007    fn decr_by(&self, key: &str, step: i64) -> Result<i64, CacheError> {
2008        // Redis DECRBY 等价于 INCRBY(-step)
2009        self.incr_by(key, -step)
2010    }
2011
2012    fn flush_db(&self) -> Result<(), CacheError> {
2013        let mut kv = self.kv.write();
2014        kv.clear();
2015        let mut sets = self.sets.write();
2016        sets.clear();
2017        Ok(())
2018    }
2019
2020    fn sadd(&self, key: &str, member: &str) -> Result<i64, CacheError> {
2021        let mut sets = self.sets.write();
2022        let set = sets.entry(key.to_string()).or_default();
2023        let added = set.insert(member.to_string()) as i64;
2024        Ok(added)
2025    }
2026
2027    fn smembers(&self, key: &str) -> Result<Vec<String>, CacheError> {
2028        let sets = self.sets.read();
2029        Ok(sets
2030            .get(key)
2031            .map(|s| s.iter().cloned().collect())
2032            .unwrap_or_default())
2033    }
2034}
2035
2036/// Redis 缓存驱动(对齐 PHP `think\cache\driver\Redis`)
2037///
2038/// 基于 `RedisBackend` trait,提供 PHP think-orm Redis 驱动的等价实现。
2039///
2040/// ## PHP 行为对齐
2041///
2042/// 1. **`set` 行为**(PHP 第 133-152 行):
2043///    - `expire > 0` → `SETEX(key, expire, value)`
2044///    - `expire = 0` → `SET(key, value)`
2045///
2046/// 2. **`inc/dec` 行为**(PHP 第 161-182 行):
2047///    - 直接 `INCRBY`/`DECRBY`,**不经 serialize**
2048///    - key 不存在时 Redis 初始化为 0
2049///    - 返回新值(i64)
2050///
2051/// 3. **`has` 行为**(PHP 第 100-103 行):
2052///    - `EXISTS(key)` ? true : false
2053///
2054/// 4. **`delete` 行为**(PHP 第 190-197 行):
2055///    - `DEL(key)` > 0 返回 true
2056///
2057/// 5. **`clear` 行为**(PHP 第 204-209 行):
2058///    - `FLUSHDB()`
2059///
2060/// 6. **`append`(tag)行为**(PHP 第 230-234 行):
2061///    - `SADD(key, value)` — 用 Set 存储 tag 成员
2062///
2063/// 7. **`getTagItems` 行为**(PHP 第 242-247 行):
2064///    - `SMEMBERS(key)` — 返回 Set 全部成员
2065///
2066/// 8. **`clearTag` 行为**(PHP 第 217-221 行):
2067///    - `DEL(keys...)` — 批量删除
2068///
2069/// ## key 构造
2070///
2071/// - `getCacheKey(name)` = `prefix + name`(对齐 PHP `Driver::getCacheKey`)
2072/// - `getTagKey(tag)` = `tag_prefix + md5(tag)`(对齐 PHP `Driver::getTagKey`)
2073///
2074/// ## 使用示例
2075///
2076/// ```ignore
2077/// use sz_rust_cache_facade::{RedisCacheDriver, RedisConfig, Cache};
2078///
2079/// let driver = RedisCacheDriver::new(RedisConfig::default());
2080/// let cache = Cache::new();
2081/// cache.register_store("redis", Box::new(driver));
2082/// cache.set_default_store("redis").unwrap();
2083///
2084/// cache.set("key", "value", None).unwrap();
2085/// assert_eq!(cache.get::<String>("key").unwrap(), Some("value".to_string()));
2086/// ```
2087pub struct RedisCacheDriver {
2088    backend: Box<dyn RedisBackend>,
2089    config: RedisConfig,
2090}
2091
2092impl RedisCacheDriver {
2093    /// 创建 Redis 缓存驱动(用 Mock backend)
2094    ///
2095    /// 对齐 PHP `new \think\cache\driver\Redis($options)`。
2096    pub fn new(config: RedisConfig) -> Self {
2097        Self::with_backend(config, Box::new(MockRedisBackend::new()))
2098    }
2099
2100    /// 创建 Redis 缓存驱动(自定义 backend)
2101    ///
2102    /// 应用层可注入真实 Redis backend(如 `redis::Connection` 包装)。
2103    pub fn with_backend(config: RedisConfig, backend: Box<dyn RedisBackend>) -> Self {
2104        Self { backend, config }
2105    }
2106
2107    /// 获取配置引用
2108    pub fn config(&self) -> &RedisConfig {
2109        &self.config
2110    }
2111
2112    /// 获取 backend 引用(用于高级操作)
2113    pub fn backend(&self) -> &dyn RedisBackend {
2114        self.backend.as_ref()
2115    }
2116
2117    /// 追加 TagSet 数据(对齐 PHP `Redis::append`)
2118    ///
2119    /// PHP `Redis::append(name, value)` 第 230-234 行:
2120    /// ```php
2121    /// public function append(string $name, $value): void
2122    /// {
2123    ///     $key = $this->getCacheKey($name);
2124    ///     $this->handler->sAdd($key, $value);
2125    /// }
2126    /// ```
2127    ///
2128    /// **注意**:PHP `think\cache\driver\Redis` 重写了父类 `Driver::append`
2129    /// (父类用 `push`,Redis 驱动用 `SADD`)。
2130    pub fn append(&self, name: &str, value: &str) -> Result<(), CacheError> {
2131        let key = self.get_cache_key(name);
2132        self.backend.sadd(&key, value)?;
2133        Ok(())
2134    }
2135
2136    /// 获取标签包含的缓存标识(对齐 PHP `Redis::getTagItems`)
2137    ///
2138    /// PHP `Redis::getTagItems(tag)` 第 242-247 行:
2139    /// ```php
2140    /// public function getTagItems(string $tag): array
2141    /// {
2142    ///     $name = $this->getTagKey($tag);
2143    ///     $key  = $this->getCacheKey($name);
2144    ///     return $this->handler->sMembers($key);
2145    /// }
2146    /// ```
2147    pub fn get_tag_items(&self, tag: &str) -> Result<Vec<String>, CacheError> {
2148        let name = self.get_tag_key(tag);
2149        let key = self.get_cache_key(&name);
2150        self.backend.smembers(&key)
2151    }
2152
2153    /// 删除缓存标签(对齐 PHP `Redis::clearTag`)
2154    ///
2155    /// PHP `Redis::clearTag(keys)` 第 217-221 行:
2156    /// ```php
2157    /// public function clearTag(array $keys): void
2158    /// {
2159    ///     $this->handler->del($keys);
2160    /// }
2161    /// ```
2162    pub fn clear_tag(&self, keys: &[&str]) -> Result<(), CacheError> {
2163        self.backend.del_many(keys)?;
2164        Ok(())
2165    }
2166
2167    /// 获取 tag key(公开接口,用于测试和调试)
2168    pub fn tag_key(&self, tag: &str) -> String {
2169        self.get_tag_key(tag)
2170    }
2171
2172    /// 获取 cache key(公开接口,用于测试和调试)
2173    pub fn cache_key(&self, name: &str) -> String {
2174        self.get_cache_key(name)
2175    }
2176}
2177
2178impl CacheDriver for RedisCacheDriver {
2179    fn get_raw(&self, key: &str) -> Result<Option<Vec<u8>>, CacheError> {
2180        let cache_key = self.get_cache_key(key);
2181        self.backend.get(&cache_key)
2182    }
2183
2184    fn set_raw(&self, key: &str, value: Vec<u8>, ttl: Option<Duration>) -> Result<(), CacheError> {
2185        let cache_key = self.get_cache_key(key);
2186        // 对齐 PHP: $expire = is_null($ttl) ? $this->options['expire'] : $ttl
2187        let effective_ttl = ttl.or(self.config.expire);
2188        // 对齐 PHP: if ($expire) { setex } else { set }
2189        match effective_ttl {
2190            Some(t) if t > Duration::ZERO => self.backend.set_ex(&cache_key, value, t),
2191            _ => self.backend.set(&cache_key, value),
2192        }
2193    }
2194
2195    fn delete(&self, key: &str) -> Result<(), CacheError> {
2196        let cache_key = self.get_cache_key(key);
2197        // PHP Redis::delete 返回 bool(del 数量 > 0),但 CacheDriver::delete 返回 ()
2198        self.backend.del(&cache_key)?;
2199        Ok(())
2200    }
2201
2202    fn has(&self, key: &str) -> Result<bool, CacheError> {
2203        let cache_key = self.get_cache_key(key);
2204        // 对齐 PHP: return $this->handler->exists($key) ? true : false
2205        self.backend.exists(&cache_key)
2206    }
2207
2208    /// 重写 inc(对齐 PHP `Redis::inc`,直接 INCRBY,不经 serialize)
2209    ///
2210    /// PHP `Redis::inc(name, step)` 第 161-167 行:
2211    /// ```php
2212    /// public function inc(string $name, int $step = 1)
2213    /// {
2214    ///     $this->writeTimes++;
2215    ///     $key = $this->getCacheKey($name);
2216    ///     return $this->handler->incrby($key, $step);
2217    /// }
2218    /// ```
2219    ///
2220    /// **关键差异**:File 驱动读取 → 加减 → 写回(经 serialize 层);
2221    /// Redis 驱动直接 INCRBY(不经 serialize)。Redis 自身处理 key 不存在
2222    /// 的情况(初始化为 0)。
2223    fn inc(&self, key: &str, step: i64) -> Result<i64, CacheError> {
2224        let cache_key = self.get_cache_key(key);
2225        self.backend.incr_by(&cache_key, step)
2226    }
2227
2228    /// 重写 dec(对齐 PHP `Redis::dec`,直接 DECRBY,不经 serialize)
2229    fn dec(&self, key: &str, step: i64) -> Result<i64, CacheError> {
2230        let cache_key = self.get_cache_key(key);
2231        self.backend.decr_by(&cache_key, step)
2232    }
2233
2234    fn clear(&self) -> Result<(), CacheError> {
2235        // 对齐 PHP: $this->handler->flushDB()
2236        self.backend.flush_db()
2237    }
2238
2239    // ========================================================================
2240    // 缓存标签重写(对齐 PHP think\cache\driver\Redis tag 相关方法)
2241    // ========================================================================
2242
2243    /// 重写 `getCacheKey`(对齐 PHP `Driver::getCacheKey`)
2244    ///
2245    /// PHP: `return $this->options['prefix'] . $name;`
2246    fn get_cache_key(&self, name: &str) -> String {
2247        format!("{}{}", self.config.prefix, name)
2248    }
2249
2250    /// 重写 `getTagKey`(对齐 PHP `Driver::getTagKey`)
2251    ///
2252    /// PHP: `return $this->options['tag_prefix'] . md5($tag);`
2253    fn get_tag_key(&self, tag: &str) -> String {
2254        let md5_hex = compute_md5(tag);
2255        format!("{}{}", self.config.tag_prefix, md5_hex)
2256    }
2257
2258    /// 重写 `tag_append`(对齐 PHP `Redis::append`,使用 `sAdd` 而非 `push`)
2259    ///
2260    /// PHP `Redis::append(name, value)` 第 230-234 行:
2261    /// ```php
2262    /// public function append(string $name, $value): void
2263    /// {
2264    ///     $key = $this->getCacheKey($name);
2265    ///     $this->handler->sAdd($key, $value);
2266    /// }
2267    /// ```
2268    ///
2269    /// **关键差异**:PHP `think\cache\driver\Redis` 重写了父类 `Driver::append`
2270    /// (父类用 `push` = get→append→set,Redis 驱动用 `SADD` = 原子 Set 操作)。
2271    fn tag_append(&self, tag_key: &str, cache_key: &str) -> Result<(), CacheError> {
2272        let key = self.get_cache_key(tag_key);
2273        self.backend.sadd(&key, cache_key)?;
2274        Ok(())
2275    }
2276
2277    /// 重写 `tag_items`(对齐 PHP `Redis::getTagItems`,使用 `sMembers`)
2278    ///
2279    /// PHP `Redis::getTagItems(tag)` 第 242-247 行:
2280    /// ```php
2281    /// public function getTagItems(string $tag): array
2282    /// {
2283    ///     $name = $this->getTagKey($tag);
2284    ///     $key  = $this->getCacheKey($name);
2285    ///     return $this->handler->sMembers($key);
2286    /// }
2287    /// ```
2288    fn tag_items(&self, tag: &str) -> Result<Vec<String>, CacheError> {
2289        let name = self.get_tag_key(tag);
2290        let key = self.get_cache_key(&name);
2291        self.backend.smembers(&key)
2292    }
2293
2294    /// 重写 `tag_clear`(对齐 PHP `Redis::clearTag`,raw del 不应用前缀)
2295    ///
2296    /// PHP `Redis::clearTag(keys)` 第 217-221 行:
2297    /// ```php
2298    /// public function clearTag(array $keys): void
2299    /// {
2300    ///     $this->handler->del($keys);
2301    /// }
2302    /// ```
2303    ///
2304    /// **关键**:`keys` 已是 `prefix + name` 格式(来自 `tag_items` 返回值),
2305    /// 因此直接 `del_many`,**不得**再次应用 `getCacheKey`。
2306    fn tag_clear(&self, keys: &[String]) -> Result<(), CacheError> {
2307        let key_refs: Vec<&str> = keys.iter().map(|s| s.as_str()).collect();
2308        self.backend.del_many(&key_refs)?;
2309        Ok(())
2310    }
2311}
2312
2313/// 计算 MD5 哈希(对齐 PHP `md5()` 函数)
2314///
2315/// PHP `md5("hello")` 返回 32 字符小写十六进制字符串。
2316pub(crate) fn compute_md5(s: &str) -> String {
2317    let mut hasher = Md5::new();
2318    hasher.update(s.as_bytes());
2319    let result = hasher.finalize();
2320    hex::encode(result)
2321}
2322
2323// ============================================================================
2324// MultiLevelCacheDriver — 多级缓存驱动(复用 sz_rust_orm_facade::MultiLevelCache)
2325// ============================================================================
2326
2327/// 多级缓存驱动(对齐 PHP think-cache 多驱动场景)
2328///
2329/// PHP think-cache 本身没有显式的 MultiLevelCache 概念,但业务层常通过
2330/// `Cache::store('redis')` / `Cache::store('file')` 切换驱动。本驱动封装
2331/// `sz_rust_orm_facade::MultiLevelCache`,提供 L1(内存)→ L2(Redis)级联查询:
2332///
2333/// - `get`:从高到低查询,命中后回填低层(带 TTL 保留)
2334/// - `set`:写入所有层级
2335/// - `delete`:删除所有层级
2336/// - `has`:任一层级存在即返回 true
2337/// - `clear`:清空所有层级
2338/// - `inc`/`dec`:委托到第一层(最高级),读取→加减→写回
2339///
2340/// ## 使用示例
2341///
2342/// ```ignore
2343/// use sz_rust_cache_facade::{MultiLevelCacheDriver, MemoryCacheDriver};
2344/// use sz_rust_orm_facade::MemoryCache;
2345///
2346/// let l1 = MemoryCache::new();
2347/// let l2 = MemoryCache::with_ttl(std::time::Duration::from_secs(60));
2348/// let driver = MultiLevelCacheDriver::new()
2349///     .add_level(Box::new(l1))
2350///     .add_level(Box::new(l2));
2351/// ```
2352pub struct MultiLevelCacheDriver {
2353    inner: sz_rust_orm_facade::MultiLevelCache,
2354}
2355
2356impl Default for MultiLevelCacheDriver {
2357    fn default() -> Self {
2358        Self::new()
2359    }
2360}
2361
2362impl MultiLevelCacheDriver {
2363    /// 创建空的多级缓存驱动
2364    pub fn new() -> Self {
2365        Self {
2366            inner: sz_rust_orm_facade::MultiLevelCache::new(),
2367        }
2368    }
2369
2370    /// 添加缓存层级(链式调用,先添加的优先级高)
2371    ///
2372    /// 对齐 sz_rust_orm_facade::MultiLevelCache::add_cache
2373    pub fn add_level(mut self, cache: Box<dyn InnerCache>) -> Self {
2374        self.inner = self.inner.add_cache(cache);
2375        self
2376    }
2377
2378    /// 获取底层 MultiLevelCache 引用(用于 ttl 等底层查询)
2379    pub fn inner(&self) -> &sz_rust_orm_facade::MultiLevelCache {
2380        &self.inner
2381    }
2382}
2383
2384impl CacheDriver for MultiLevelCacheDriver {
2385    fn get_raw(&self, key: &str) -> Result<Option<Vec<u8>>, CacheError> {
2386        self.inner.get(key)
2387    }
2388
2389    fn set_raw(&self, key: &str, value: Vec<u8>, ttl: Option<Duration>) -> Result<(), CacheError> {
2390        self.inner.set(key, value, ttl)
2391    }
2392
2393    fn delete(&self, key: &str) -> Result<(), CacheError> {
2394        self.inner.delete(key)
2395    }
2396
2397    fn has(&self, key: &str) -> Result<bool, CacheError> {
2398        self.inner.exists(key)
2399    }
2400
2401    fn inc(&self, key: &str, step: i64) -> Result<i64, CacheError> {
2402        // 对齐 PHP File 驱动 inc/dec 行为:读取 → 解析为 i64 → 加减 → 写回
2403        // 多级缓存下,inc/dec 委托到第一层(最高级)
2404        let current = match self.inner.get(key)? {
2405            Some(bytes) => String::from_utf8(bytes)
2406                .map_err(|e| CacheError::DeserializationError(e.to_string()))?
2407                .parse::<i64>()
2408                .unwrap_or(0),
2409            None => 0,
2410        };
2411        let new_value = current + step;
2412        let new_bytes = new_value.to_string().into_bytes();
2413        // 保留原 TTL:查询第一层的 ttl,写回时不重新设置
2414        let ttl = self.inner.ttl(key).ok().flatten();
2415        self.inner.set(key, new_bytes, ttl)?;
2416        Ok(new_value)
2417    }
2418
2419    fn dec(&self, key: &str, step: i64) -> Result<i64, CacheError> {
2420        // 对齐 PHP File 驱动:读取 → 解析为 i64 → 减 → 写回
2421        let current = match self.inner.get(key)? {
2422            Some(bytes) => String::from_utf8(bytes)
2423                .map_err(|e| CacheError::DeserializationError(e.to_string()))?
2424                .parse::<i64>()
2425                .unwrap_or(0),
2426            None => 0,
2427        };
2428        let new_value = current - step;
2429        let new_bytes = new_value.to_string().into_bytes();
2430        let ttl = self.inner.ttl(key).ok().flatten();
2431        self.inner.set(key, new_bytes, ttl)?;
2432        Ok(new_value)
2433    }
2434
2435    fn clear(&self) -> Result<(), CacheError> {
2436        self.inner.clear()
2437    }
2438}
2439
2440// ============================================================================
2441// TagSet — 缓存标签集合(对齐 PHP think\cache\TagSet)
2442// ============================================================================
2443
2444/// 缓存标签集合(对齐 PHP `think\cache\TagSet`)
2445///
2446/// PHP `TagSet`(132 行)提供基于标签的缓存批量管理:
2447///
2448/// - `set(name, value, expire)`:写入缓存 + 追加 key 到标签集合
2449/// - `append(name)`:追加 key 到所有标签
2450/// - `clear()`:清除所有标签下的缓存
2451///
2452/// ## PHP 对齐
2453///
2454/// PHP `TagSet::set` 第 52-59 行:
2455/// ```php
2456/// public function set(string $name, $value, $expire = null): bool
2457/// {
2458///     $this->handler->set($name, $value, $expire);
2459///     $this->append($name);
2460///     return true;
2461/// }
2462/// ```
2463///
2464/// PHP `TagSet::append` 第 67-75 行:
2465/// ```php
2466/// public function append(string $name): void
2467/// {
2468///     $name = $this->handler->getCacheKey($name);
2469///     foreach ($this->tag as $tag) {
2470///         $key = $this->handler->getTagKey($tag);
2471///         $this->handler->append($key, $name);
2472///     }
2473/// }
2474/// ```
2475///
2476/// PHP `TagSet::clear` 第 119-131 行:
2477/// ```php
2478/// public function clear(): bool
2479/// {
2480///     foreach ($this->tag as $tag) {
2481///         $names = $this->handler->getTagItems($tag);
2482///         $this->handler->clearTag($names);
2483///         $key = $this->handler->getTagKey($tag);
2484///         $this->handler->delete($key);
2485///     }
2486///     return true;
2487/// }
2488/// ```
2489///
2490/// ## 生命周期
2491///
2492/// `TagSet<'a>` 持有 `&'a Cache` 引用,确保在 TagSet 使用期间 Cache 不会被释放。
2493/// 通过 `Cache::tag()` 或 `Cache::tag_many()` 创建。
2494pub struct TagSet<'a> {
2495    /// 标签名列表(对齐 PHP `TagSet::$tag`)
2496    tags: Vec<String>,
2497    /// 缓存句柄(对齐 PHP `TagSet::$handler`)
2498    cache: &'a Cache,
2499}
2500
2501impl<'a> TagSet<'a> {
2502    /// 写入缓存并追加到标签(对齐 PHP `TagSet::set`)
2503    ///
2504    /// PHP `TagSet::set(name, value, expire)` 第 52-59 行:
2505    /// 1. `handler->set(name, value, expire)` — 写入缓存
2506    /// 2. `append(name)` — 追加 key 到所有标签
2507    ///
2508    /// ## 参数
2509    ///
2510    /// - `key`:缓存键
2511    /// - `value`:缓存值(实现 `Serialize`)
2512    /// - `ttl`:过期时间(`None` 永不过期)
2513    pub fn set<T: Serialize>(
2514        &self,
2515        key: &str,
2516        value: T,
2517        ttl: Option<Duration>,
2518    ) -> Result<(), CacheError> {
2519        // 对齐 PHP: $this->handler->set($name, $value, $expire);
2520        self.cache.set(key, value, ttl)?;
2521        // 对齐 PHP: $this->append($name);
2522        self.append(key)
2523    }
2524
2525    /// 追加缓存 key 到所有标签(对齐 PHP `TagSet::append`)
2526    ///
2527    /// PHP `TagSet::append(name)` 第 67-75 行:
2528    /// ```php
2529    /// $name = $this->handler->getCacheKey($name);
2530    /// foreach ($this->tag as $tag) {
2531    ///     $key = $this->handler->getTagKey($tag);
2532    ///     $this->handler->append($key, $name);
2533    /// }
2534    /// ```
2535    ///
2536    /// ## 行为
2537    ///
2538    /// 1. 计算 `cache_key = getCacheKey(name)`(应用前缀)
2539    /// 2. 对每个 tag:计算 `tag_key = getTagKey(tag)`,调用 `driver.tag_append(tag_key, cache_key)`
2540    pub fn append(&self, key: &str) -> Result<(), CacheError> {
2541        let mgr = self.cache.manager.read();
2542        let driver = mgr.default_store()?;
2543        // 对齐 PHP: $name = $this->handler->getCacheKey($name);
2544        let cache_key = driver.get_cache_key(key);
2545        // 对齐 PHP: foreach ($this->tag as $tag) { ... }
2546        for tag in &self.tags {
2547            // 对齐 PHP: $key = $this->handler->getTagKey($tag);
2548            let tag_key = driver.get_tag_key(tag);
2549            // 对齐 PHP: $this->handler->append($key, $name);
2550            driver.tag_append(&tag_key, &cache_key)?;
2551        }
2552        Ok(())
2553    }
2554
2555    /// 清除所有标签下的缓存(对齐 PHP `TagSet::clear`)
2556    ///
2557    /// PHP `TagSet::clear()` 第 119-131 行:
2558    /// ```php
2559    /// foreach ($this->tag as $tag) {
2560    ///     $names = $this->handler->getTagItems($tag);
2561    ///     $this->handler->clearTag($names);
2562    ///     $key = $this->handler->getTagKey($tag);
2563    ///     $this->handler->delete($key);
2564    /// }
2565    /// ```
2566    ///
2567    /// ## 行为
2568    ///
2569    /// 对每个 tag:
2570    /// 1. `tag_items(tag)` — 获取该标签下所有缓存 key(已应用前缀)
2571    /// 2. `tag_clear(items)` — 批量删除这些缓存 key(raw delete,不应用前缀)
2572    /// 3. `delete(get_tag_key(tag))` — 删除标签 key 本身(delete 应用前缀)
2573    pub fn clear(&self) -> Result<(), CacheError> {
2574        let mgr = self.cache.manager.read();
2575        let driver = mgr.default_store()?;
2576        for tag in &self.tags {
2577            // 对齐 PHP: $names = $this->handler->getTagItems($tag);
2578            let items = driver.tag_items(tag)?;
2579            // 对齐 PHP: $this->handler->clearTag($names);
2580            driver.tag_clear(&items)?;
2581            // 对齐 PHP: $key = $this->handler->getTagKey($tag);
2582            let tag_key = driver.get_tag_key(tag);
2583            // 对齐 PHP: $this->handler->delete($key);
2584            driver.delete(&tag_key)?;
2585        }
2586        Ok(())
2587    }
2588
2589    /// 获取标签列表(用于测试和调试)
2590    pub fn tags(&self) -> &[String] {
2591        &self.tags
2592    }
2593}
2594
2595// ============================================================================
2596// 单元测试
2597// ============================================================================
2598
2599#[cfg(test)]
2600mod tests {
2601    use crate::*;
2602    use serde::Deserialize;
2603    use std::sync::Barrier;
2604
2605    /// 创建带默认驱动的测试用 Cache
2606    fn make_cache() -> Cache {
2607        let cache = Cache::new();
2608        cache.register_default(MemoryCacheDriver::new());
2609        cache
2610    }
2611
2612    // ========================================================================
2613    // 组 1:php_is_numeric 对齐 PHP is_numeric
2614    // ========================================================================
2615
2616    #[test]
2617    fn test_php_is_numeric_integer() {
2618        // 对齐 PHP: is_numeric("42") === true
2619        assert!(php_is_numeric("42"));
2620        assert!(php_is_numeric("-42"));
2621        assert!(php_is_numeric("+42"));
2622        assert!(php_is_numeric("0"));
2623    }
2624
2625    #[test]
2626    fn test_php_is_numeric_float() {
2627        // 对齐 PHP: is_numeric("3.14") === true
2628        assert!(php_is_numeric("3.14"));
2629        assert!(php_is_numeric("-3.14"));
2630        assert!(php_is_numeric("+3.14"));
2631        assert!(php_is_numeric("0.0"));
2632    }
2633
2634    #[test]
2635    fn test_php_is_numeric_scientific_notation() {
2636        // 对齐 PHP: is_numeric("1e10") === true
2637        assert!(php_is_numeric("1e10"));
2638        assert!(php_is_numeric("1.5E-3"));
2639    }
2640
2641    #[test]
2642    fn test_php_is_numeric_non_numeric() {
2643        // 对齐 PHP: is_numeric("abc") === false
2644        assert!(!php_is_numeric("abc"));
2645        assert!(!php_is_numeric("12abc"));
2646        assert!(!php_is_numeric(""));
2647        assert!(!php_is_numeric("0x1A")); // PHP 7+ 不识别十六进制字符串
2648        assert!(!php_is_numeric("null"));
2649        assert!(!php_is_numeric("true"));
2650    }
2651
2652    // ========================================================================
2653    // 组 2:php_serialize / php_unserialize 序列化策略
2654    // ========================================================================
2655
2656    #[test]
2657    fn test_php_serialize_integer_to_number() {
2658        // 对齐 PHP: serialize(42) === "42"(is_numeric 短路)
2659        let v = php_serialize(&42i64).unwrap();
2660        assert!(matches!(v, CacheValue::Number(_)));
2661        if let CacheValue::Number(s) = v {
2662            assert_eq!(s, "42");
2663        }
2664    }
2665
2666    #[test]
2667    fn test_php_serialize_float_to_number() {
2668        // 对齐 PHP: serialize(2.5) === "2.5"(is_numeric 短路)
2669        // 注:避开 3.14(clippy approx_constant 误报为 PI 近似值)
2670        let v = php_serialize(&2.5f64).unwrap();
2671        assert!(matches!(v, CacheValue::Number(_)));
2672        if let CacheValue::Number(s) = v {
2673            assert_eq!(s, "2.5");
2674        }
2675    }
2676
2677    #[test]
2678    fn test_php_serialize_string_to_json() {
2679        // 对齐 PHP: serialize("Alice") === 's:5:"Alice";'(非 numeric 走 serialize)
2680        // Rust 端用 serde_json,"Alice" → "\"Alice\""
2681        let v = php_serialize(&"Alice".to_string()).unwrap();
2682        assert!(matches!(v, CacheValue::Json(_)));
2683        if let CacheValue::Json(s) = v {
2684            assert_eq!(s, "\"Alice\"");
2685        }
2686    }
2687
2688    #[test]
2689    fn test_php_serialize_numeric_string_to_number() {
2690        // PHP is_numeric("42") === true,但 serde_json 序列化 String "42" → "\"42\""(带引号)
2691        // 因此 Rust 端把 String "42" 视为非 numeric,存为 Json
2692        // 这是 PHP 与 Rust 序列化机制的差异:PHP serialize 直接接收 $data 值,
2693        // 若 $data 是字符串 "42",PHP is_numeric 检查的是字符串内容 "42"(true)
2694        // Rust serde_json 序列化 String "42" → "\"42\""(带引号),php_is_numeric 检查的是 "\"42\""(false)
2695        //
2696        // 这个差异是预期的:PHP 的 $value 是弱类型,Rust 的 T: Serialize 是强类型。
2697        // 业务对齐通过 i64/f64 类型直接调用 set 来保证 is_numeric 短路生效。
2698        let v = php_serialize(&"42".to_string()).unwrap();
2699        assert!(matches!(v, CacheValue::Json(_))); // 注意:是 Json,不是 Number
2700    }
2701
2702    #[test]
2703    fn test_php_serialize_array_to_json() {
2704        // 对齐 PHP: serialize([1, 2, 3])(非 numeric 走 serialize)
2705        let v = php_serialize(&vec![1, 2, 3]).unwrap();
2706        assert!(matches!(v, CacheValue::Json(_)));
2707        if let CacheValue::Json(s) = v {
2708            assert_eq!(s, "[1,2,3]");
2709        }
2710    }
2711
2712    #[test]
2713    fn test_php_unserialize_number_returns_string() {
2714        // PHP bug 复刻:unserialize 对 is_numeric 返回 string,而非 int
2715        // Rust 端通过泛型 T = String 来对齐
2716        let v = CacheValue::Number("42".to_string());
2717        let result: Option<String> = php_unserialize(&v).unwrap();
2718        assert_eq!(result, Some("42".to_string()));
2719    }
2720
2721    #[test]
2722    fn test_php_unserialize_json_returns_struct() {
2723        // unserialize 对 JSON 字符串还原为原始结构
2724        let v = CacheValue::Json("\"Alice\"".to_string());
2725        let result: Option<String> = php_unserialize(&v).unwrap();
2726        assert_eq!(result, Some("Alice".to_string()));
2727
2728        let v = CacheValue::Json("[1,2,3]".to_string());
2729        let result: Option<Vec<i64>> = php_unserialize(&v).unwrap();
2730        assert_eq!(result, Some(vec![1, 2, 3]));
2731    }
2732
2733    #[test]
2734    fn test_php_unserialize_number_to_int_via_parse() {
2735        // 对齐 PHP 业务代码 (int) Cache::get('count') 强转模式
2736        // Rust 端:get::<String>() + .parse::<i64>()
2737        let v = CacheValue::Number("42".to_string());
2738        let s: String = php_unserialize(&v).unwrap().unwrap();
2739        let n: i64 = s.parse().unwrap();
2740        assert_eq!(n, 42);
2741    }
2742
2743    // ========================================================================
2744    // 组 3:CacheValue from_bytes / to_bytes 往返
2745    // ========================================================================
2746
2747    #[test]
2748    fn test_cache_value_number_roundtrip() {
2749        let v = CacheValue::Number("42".to_string());
2750        let bytes = v.to_bytes();
2751        let restored = CacheValue::from_bytes(&bytes).unwrap();
2752        assert_eq!(v, restored);
2753    }
2754
2755    #[test]
2756    fn test_cache_value_json_roundtrip() {
2757        let v = CacheValue::Json("\"Alice\"".to_string());
2758        let bytes = v.to_bytes();
2759        let restored = CacheValue::from_bytes(&bytes).unwrap();
2760        assert_eq!(v, restored);
2761    }
2762
2763    #[test]
2764    fn test_cache_value_array_roundtrip() {
2765        let v = CacheValue::Json("[1,2,3]".to_string());
2766        let bytes = v.to_bytes();
2767        let restored = CacheValue::from_bytes(&bytes).unwrap();
2768        assert_eq!(v, restored);
2769    }
2770
2771    #[test]
2772    fn test_cache_value_from_bytes_numeric_string_becomes_number() {
2773        // "42" 字节 → Number(对齐 PHP unserialize is_numeric 短路)
2774        let bytes = b"42".to_vec();
2775        let v = CacheValue::from_bytes(&bytes).unwrap();
2776        assert!(matches!(v, CacheValue::Number(_)));
2777    }
2778
2779    #[test]
2780    fn test_cache_value_from_bytes_json_string_becomes_json() {
2781        // "\"Alice\"" 字节 → Json
2782        let bytes = b"\"Alice\"".to_vec();
2783        let v = CacheValue::from_bytes(&bytes).unwrap();
2784        assert!(matches!(v, CacheValue::Json(_)));
2785    }
2786
2787    // ========================================================================
2788    // 组 4:MemoryCacheDriver 基本操作
2789    // ========================================================================
2790
2791    #[test]
2792    fn test_memory_driver_set_get_raw() {
2793        let driver = MemoryCacheDriver::new();
2794        driver.set_raw("key", b"value".to_vec(), None).unwrap();
2795        let val = driver.get_raw("key").unwrap();
2796        assert_eq!(val, Some(b"value".to_vec()));
2797    }
2798
2799    #[test]
2800    fn test_memory_driver_delete() {
2801        let driver = MemoryCacheDriver::new();
2802        driver.set_raw("key", b"value".to_vec(), None).unwrap();
2803        driver.delete("key").unwrap();
2804        let val = driver.get_raw("key").unwrap();
2805        assert_eq!(val, None);
2806    }
2807
2808    #[test]
2809    fn test_memory_driver_has() {
2810        let driver = MemoryCacheDriver::new();
2811        driver.set_raw("key", b"value".to_vec(), None).unwrap();
2812        assert!(driver.has("key").unwrap());
2813        assert!(!driver.has("nonexistent").unwrap());
2814    }
2815
2816    #[test]
2817    fn test_memory_driver_clear() {
2818        let driver = MemoryCacheDriver::new();
2819        driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
2820        driver.set_raw("key2", b"value2".to_vec(), None).unwrap();
2821        driver.clear().unwrap();
2822        assert!(!driver.has("key1").unwrap());
2823        assert!(!driver.has("key2").unwrap());
2824    }
2825
2826    #[test]
2827    fn test_memory_driver_ttl_expiration() {
2828        let driver = MemoryCacheDriver::new();
2829        driver
2830            .set_raw("key", b"value".to_vec(), Some(Duration::from_millis(50)))
2831            .unwrap();
2832        assert!(driver.get_raw("key").unwrap().is_some());
2833        std::thread::sleep(Duration::from_millis(100));
2834        assert!(driver.get_raw("key").unwrap().is_none());
2835    }
2836
2837    #[test]
2838    fn test_memory_driver_inc_default_implementation() {
2839        // 默认实现:File 驱动行为(读取 → 加减 → 写回)
2840        let driver = MemoryCacheDriver::new();
2841
2842        // 键不存在:初始化为 step
2843        let v = driver.inc("counter", 5).unwrap();
2844        assert_eq!(v, 5);
2845
2846        // 键存在:加 step
2847        let v = driver.inc("counter", 3).unwrap();
2848        assert_eq!(v, 8);
2849    }
2850
2851    #[test]
2852    fn test_memory_driver_dec_default_implementation() {
2853        let driver = MemoryCacheDriver::new();
2854
2855        // 键不存在:初始化为 -step(即 0 - step)
2856        let v = driver.dec("counter", 3).unwrap();
2857        assert_eq!(v, -3);
2858
2859        // 键存在:减 step
2860        let v = driver.dec("counter", 2).unwrap();
2861        assert_eq!(v, -5);
2862    }
2863
2864    // ========================================================================
2865    // 组 5:CacheManager 多驱动管理
2866    // ========================================================================
2867
2868    #[test]
2869    fn test_cache_manager_register_and_get_default() {
2870        let mut mgr = CacheManager::new();
2871        mgr.register_store("default", Box::new(MemoryCacheDriver::new()));
2872
2873        let driver = mgr.default_store().unwrap();
2874        driver.set_raw("key", b"value".to_vec(), None).unwrap();
2875        assert_eq!(driver.get_raw("key").unwrap(), Some(b"value".to_vec()));
2876    }
2877
2878    #[test]
2879    fn test_cache_manager_multiple_stores_isolation() {
2880        let mut mgr = CacheManager::new();
2881        mgr.register_store("file", Box::new(MemoryCacheDriver::new()));
2882        mgr.register_store("redis", Box::new(MemoryCacheDriver::new()));
2883
2884        let file_driver = mgr.store("file").unwrap();
2885        let redis_driver = mgr.store("redis").unwrap();
2886
2887        file_driver
2888            .set_raw("key", b"file_value".to_vec(), None)
2889            .unwrap();
2890        redis_driver
2891            .set_raw("key", b"redis_value".to_vec(), None)
2892            .unwrap();
2893
2894        // 不同 store 隔离
2895        assert_eq!(
2896            file_driver.get_raw("key").unwrap(),
2897            Some(b"file_value".to_vec())
2898        );
2899        assert_eq!(
2900            redis_driver.get_raw("key").unwrap(),
2901            Some(b"redis_value".to_vec())
2902        );
2903    }
2904
2905    #[test]
2906    fn test_cache_manager_set_default() {
2907        let mut mgr = CacheManager::new();
2908        mgr.register_store("file", Box::new(MemoryCacheDriver::new()));
2909        mgr.register_store("redis", Box::new(MemoryCacheDriver::new()));
2910
2911        // 默认是第一个注册的(file)
2912        let driver = mgr.default_store().unwrap();
2913        driver.set_raw("file_key", b"file".to_vec(), None).unwrap();
2914        assert_eq!(driver.get_raw("file_key").unwrap(), Some(b"file".to_vec()));
2915
2916        // 切换默认到 redis
2917        mgr.set_default("redis").unwrap();
2918        let driver = mgr.default_store().unwrap();
2919        driver
2920            .set_raw("redis_key", b"redis".to_vec(), None)
2921            .unwrap();
2922        assert_eq!(
2923            driver.get_raw("redis_key").unwrap(),
2924            Some(b"redis".to_vec())
2925        );
2926    }
2927
2928    #[test]
2929    fn test_cache_manager_default_store_not_registered_error() {
2930        let mgr = CacheManager::new();
2931        let result = mgr.default_store();
2932        assert!(matches!(result, Err(CacheError::NotFound(_))));
2933    }
2934
2935    #[test]
2936    fn test_cache_manager_store_not_found_error() {
2937        let mgr = CacheManager::new();
2938        let result = mgr.store("nonexistent");
2939        assert!(matches!(result, Err(CacheError::NotFound(_))));
2940    }
2941
2942    // ========================================================================
2943    // 组 6:Cache facade set/get 基本 API
2944    // ========================================================================
2945
2946    #[test]
2947    fn test_cache_set_get_string() {
2948        let cache = make_cache();
2949        cache.set("name", "Alice", None).unwrap();
2950        let val: Option<String> = cache.get("name").unwrap();
2951        assert_eq!(val, Some("Alice".to_string()));
2952    }
2953
2954    #[test]
2955    fn test_cache_set_get_int_as_string_php_bug() {
2956        // PHP bug 复刻:is_numeric 短路 + unserialize 返回 string
2957        // 调用方需自行 parse::<i64>()
2958        let cache = make_cache();
2959        cache.set("count", 42i64, None).unwrap();
2960
2961        // 直接 get::<i64> 会失败(PHP 也不允许,需 (int) 强转)
2962        // 对齐方式:get::<String> + parse::<i64>
2963        let s: Option<String> = cache.get("count").unwrap();
2964        assert_eq!(s, Some("42".to_string()));
2965
2966        let n: i64 = s.unwrap().parse().unwrap();
2967        assert_eq!(n, 42);
2968    }
2969
2970    #[test]
2971    fn test_cache_set_get_struct() {
2972        #[derive(Serialize, Deserialize, PartialEq, Debug)]
2973        struct User {
2974            name: String,
2975            age: u32,
2976        }
2977
2978        let cache = make_cache();
2979        let user = User {
2980            name: "Alice".to_string(),
2981            age: 30,
2982        };
2983        cache.set("user:1", &user, None).unwrap();
2984
2985        let val: Option<User> = cache.get("user:1").unwrap();
2986        assert_eq!(val, Some(user));
2987    }
2988
2989    #[test]
2990    fn test_cache_set_get_vec() {
2991        let cache = make_cache();
2992        let list = vec![1, 2, 3];
2993        cache.set("list", &list, None).unwrap();
2994
2995        let val: Option<Vec<i64>> = cache.get("list").unwrap();
2996        assert_eq!(val, Some(vec![1, 2, 3]));
2997    }
2998
2999    #[test]
3000    fn test_cache_get_miss_returns_none() {
3001        let cache = make_cache();
3002        let val: Option<String> = cache.get("nonexistent").unwrap();
3003        assert_eq!(val, None);
3004    }
3005
3006    #[test]
3007    fn test_cache_get_or_default_value() {
3008        let cache = make_cache();
3009        let val: String = cache.get_or("nonexistent", "default".to_string()).unwrap();
3010        assert_eq!(val, "default");
3011    }
3012
3013    #[test]
3014    fn test_cache_set_with_ttl_expires() {
3015        let cache = make_cache();
3016        cache
3017            .set("key", "value", Some(Duration::from_millis(50)))
3018            .unwrap();
3019        assert!(cache.get::<String>("key").unwrap().is_some());
3020        std::thread::sleep(Duration::from_millis(100));
3021        assert!(cache.get::<String>("key").unwrap().is_none());
3022    }
3023
3024    // ========================================================================
3025    // 组 7:Cache facade delete / has / clear
3026    // ========================================================================
3027
3028    #[test]
3029    fn test_cache_delete() {
3030        let cache = make_cache();
3031        cache.set("key", "value", None).unwrap();
3032        assert!(cache.has("key").unwrap());
3033
3034        cache.delete("key").unwrap();
3035        assert!(!cache.has("key").unwrap());
3036
3037        // 删除不存在的 key 不报错(对齐 PHP)
3038        cache.delete("nonexistent").unwrap();
3039    }
3040
3041    #[test]
3042    fn test_cache_has_checks_ttl() {
3043        let cache = make_cache();
3044        cache
3045            .set("key", "value", Some(Duration::from_millis(50)))
3046            .unwrap();
3047        assert!(cache.has("key").unwrap());
3048
3049        std::thread::sleep(Duration::from_millis(100));
3050        // TTL 过期后 has 返回 false
3051        assert!(!cache.has("key").unwrap());
3052    }
3053
3054    #[test]
3055    fn test_cache_clear() {
3056        let cache = make_cache();
3057        cache.set("key1", "value1", None).unwrap();
3058        cache.set("key2", "value2", None).unwrap();
3059
3060        cache.clear().unwrap();
3061
3062        assert!(!cache.has("key1").unwrap());
3063        assert!(!cache.has("key2").unwrap());
3064    }
3065
3066    // ========================================================================
3067    // 组 8:Cache facade inc / dec
3068    // ========================================================================
3069
3070    #[test]
3071    fn test_cache_inc_initial_value() {
3072        // 对齐 PHP: 键不存在时初始化为 step
3073        let cache = make_cache();
3074        let v = cache.inc("counter", 5).unwrap();
3075        assert_eq!(v, 5);
3076
3077        // 验证存储的值
3078        let s: String = cache.get("counter").unwrap().unwrap();
3079        assert_eq!(s, "5");
3080    }
3081
3082    #[test]
3083    fn test_cache_inc_accumulate() {
3084        let cache = make_cache();
3085        cache.inc("counter", 5).unwrap();
3086        cache.inc("counter", 3).unwrap();
3087        let v = cache.inc("counter", 2).unwrap();
3088        assert_eq!(v, 10);
3089    }
3090
3091    #[test]
3092    fn test_cache_dec_initial_value() {
3093        // 对齐 PHP: 键不存在时初始化为 -step
3094        let cache = make_cache();
3095        let v = cache.dec("counter", 3).unwrap();
3096        assert_eq!(v, -3);
3097    }
3098
3099    #[test]
3100    fn test_cache_dec_accumulate() {
3101        let cache = make_cache();
3102        cache.set("counter", 100i64, None).unwrap();
3103        cache.dec("counter", 30).unwrap();
3104        let v = cache.dec("counter", 20).unwrap();
3105        assert_eq!(v, 50);
3106    }
3107
3108    #[test]
3109    fn test_cache_increment_default_step_1() {
3110        let cache = make_cache();
3111        let v = cache.increment("counter").unwrap();
3112        assert_eq!(v, 1);
3113        let v = cache.increment("counter").unwrap();
3114        assert_eq!(v, 2);
3115    }
3116
3117    #[test]
3118    fn test_cache_decrement_default_step_1() {
3119        let cache = make_cache();
3120        let v = cache.decrement("counter").unwrap();
3121        assert_eq!(v, -1);
3122        let v = cache.decrement("counter").unwrap();
3123        assert_eq!(v, -2);
3124    }
3125
3126    // ========================================================================
3127    // 组 9:Cache facade pull(读后删)
3128    // ========================================================================
3129
3130    #[test]
3131    fn test_cache_pull_existing_key() {
3132        // 对齐 PHP: get + delete
3133        let cache = make_cache();
3134        cache.set("key", "value", None).unwrap();
3135
3136        let val: Option<String> = cache.pull("key").unwrap();
3137        assert_eq!(val, Some("value".to_string()));
3138
3139        // pull 后 key 应被删除
3140        assert!(!cache.has("key").unwrap());
3141    }
3142
3143    #[test]
3144    fn test_cache_pull_missing_key_returns_none() {
3145        let cache = make_cache();
3146        let val: Option<String> = cache.pull("nonexistent").unwrap();
3147        assert_eq!(val, None);
3148    }
3149
3150    // ========================================================================
3151    // 组 10:Cache facade push(数组追加 + 上限 + 去重)
3152    // ========================================================================
3153
3154    #[test]
3155    fn test_cache_push_initial_array() {
3156        let cache = make_cache();
3157        cache.push("list", "a".to_string(), None).unwrap();
3158
3159        let val: Option<Vec<String>> = cache.get("list").unwrap();
3160        assert_eq!(val, Some(vec!["a".to_string()]));
3161    }
3162
3163    #[test]
3164    fn test_cache_push_appends() {
3165        let cache = make_cache();
3166        cache.push("list", "a".to_string(), None).unwrap();
3167        cache.push("list", "b".to_string(), None).unwrap();
3168        cache.push("list", "c".to_string(), None).unwrap();
3169
3170        let val: Option<Vec<String>> = cache.get("list").unwrap();
3171        assert_eq!(
3172            val,
3173            Some(vec!["a".to_string(), "b".to_string(), "c".to_string()])
3174        );
3175    }
3176
3177    #[test]
3178    fn test_cache_push_deduplication() {
3179        // 对齐 PHP array_unique:保留首次出现的元素
3180        let cache = make_cache();
3181        cache.push("list", "a".to_string(), None).unwrap();
3182        cache.push("list", "b".to_string(), None).unwrap();
3183        cache.push("list", "a".to_string(), None).unwrap(); // 重复
3184        cache.push("list", "c".to_string(), None).unwrap();
3185        cache.push("list", "b".to_string(), None).unwrap(); // 重复
3186
3187        let val: Option<Vec<String>> = cache.get("list").unwrap();
3188        assert_eq!(
3189            val,
3190            Some(vec!["a".to_string(), "b".to_string(), "c".to_string()])
3191        );
3192    }
3193
3194    #[test]
3195    fn test_cache_push_max_1000_fifo() {
3196        // 对齐 PHP array_shift:长度 > 1000 时丢弃最旧
3197        let cache = make_cache();
3198
3199        // 推入 1001 个元素
3200        for i in 0..1001i64 {
3201            cache.push("list", i, None).unwrap();
3202        }
3203
3204        let val: Option<Vec<i64>> = cache.get("list").unwrap();
3205        let list = val.unwrap();
3206
3207        // 长度应为 1000(丢弃了 0)
3208        assert_eq!(list.len(), 1000);
3209        // 第一个元素应为 1(0 被丢弃)
3210        assert_eq!(list[0], 1);
3211        // 最后一个元素应为 1000
3212        assert_eq!(list[999], 1000);
3213    }
3214
3215    #[test]
3216    fn test_cache_push_non_array_becomes_array() {
3217        // 对齐 PHP: 缓存非数组 → 创建 [value]
3218        let cache = make_cache();
3219
3220        // 先写入字符串(非数组)
3221        cache.set("key", "not_an_array".to_string(), None).unwrap();
3222
3223        // push 应覆盖为数组
3224        cache.push("key", "first".to_string(), None).unwrap();
3225
3226        let val: Option<Vec<String>> = cache.get("key").unwrap();
3227        assert_eq!(val, Some(vec!["first".to_string()]));
3228    }
3229
3230    // ========================================================================
3231    // 组 11:Cache facade remember(缓存击穿防护 + PHP bug 复刻)
3232    // ========================================================================
3233
3234    #[tokio::test]
3235    async fn test_cache_remember_cache_miss() {
3236        // 未命中:调用 callback 并写入缓存
3237        let cache = make_cache();
3238        let counter = std::sync::Arc::new(std::sync::atomic::AtomicU32::new(0));
3239        let counter_clone = counter.clone();
3240
3241        let val: i64 = cache
3242            .remember("expensive", None, || {
3243                counter_clone.fetch_add(1, std::sync::atomic::Ordering::SeqCst) as i64 + 100
3244            })
3245            .await
3246            .unwrap();
3247        assert_eq!(val, 100);
3248
3249        // 第二次调用应命中缓存,callback 不被调用
3250        let val: i64 = cache
3251            .remember("expensive", None, || {
3252                counter_clone.fetch_add(1, std::sync::atomic::Ordering::SeqCst) as i64 + 200
3253            })
3254            .await
3255            .unwrap();
3256        assert_eq!(val, 100); // 命中缓存,仍是 100
3257
3258        // callback 只被调用一次
3259        assert_eq!(counter.load(std::sync::atomic::Ordering::SeqCst), 1);
3260    }
3261
3262    #[tokio::test]
3263    async fn test_cache_remember_cache_hit_returns_cached() {
3264        let cache = make_cache();
3265        cache.set("predefined", 42i64, None).unwrap();
3266
3267        // 命中缓存,callback 不应被调用
3268        let val: i64 = cache
3269            .remember("predefined", None, || {
3270                panic!("callback should not be called on cache hit");
3271            })
3272            .await
3273            .unwrap();
3274        assert_eq!(val, 42);
3275    }
3276
3277    #[tokio::test]
3278    async fn test_cache_remember_writes_with_ttl() {
3279        let cache = make_cache();
3280        cache
3281            .remember("key", Some(Duration::from_millis(50)), || 42i64)
3282            .await
3283            .unwrap();
3284
3285        // 立即读取应命中
3286        assert_eq!(cache.get::<String>("key").unwrap(), Some("42".to_string()));
3287
3288        // 等待过期
3289        tokio::time::sleep(Duration::from_millis(100)).await;
3290        assert!(cache.get::<String>("key").unwrap().is_none());
3291    }
3292
3293    #[tokio::test]
3294    async fn test_cache_remember_releases_lock_on_success() {
3295        // 对齐 PHP: callback 成功后释放锁
3296        let cache = make_cache();
3297        cache.remember("key", None, || 42i64).await.unwrap();
3298
3299        // 锁应被释放
3300        assert!(!cache.has("key_lock").unwrap());
3301    }
3302
3303    #[tokio::test]
3304    async fn test_cache_remember_releases_lock_on_panic() {
3305        // 对齐 PHP finally 块:callback panic 时也应释放锁
3306        // Rust 端:由于我们用 FnOnce() -> T(无 Result),panic 会传播
3307        // 但锁会被泄漏(因为 panic 会跳过 delete)
3308        // 这是 PHP 行为的"复刻"(PHP 也存在 try/finally 在 fatal error 时不执行)
3309        // 此测试验证正常路径下锁被释放
3310        let cache = make_cache();
3311        let _ = cache.remember("key", None, || 42i64).await;
3312        assert!(!cache.has("key_lock").unwrap());
3313    }
3314
3315    #[tokio::test]
3316    async fn test_cache_remember_lock_has_no_ttl_php_bug() {
3317        // PHP 源码 bug 复刻:锁 key 无 TTL
3318        // 验证方式:remember 期间,锁 key 被设置为 1,且无 TTL
3319        // 此测试通过代码审查确认(PHP 源码第 305 行:$this->set($lockName, 1) 无第三个参数)
3320        // 函数签名 set(&self, key, value, ttl: Option<Duration>),ttl = None 即无 TTL
3321
3322        // 此处验证锁被正确释放(间接验证锁机制正常工作)
3323        let cache = make_cache();
3324        cache.remember("key", None, || 42i64).await.unwrap();
3325        assert!(!cache.has("key_lock").unwrap());
3326    }
3327
3328    #[tokio::test]
3329    async fn test_cache_remember_async_cache_miss() {
3330        // 未命中:调用 async callback 并写入缓存
3331        let cache = make_cache();
3332        let counter = std::sync::Arc::new(std::sync::atomic::AtomicU32::new(0));
3333        let counter_clone = counter.clone();
3334
3335        let val: i64 = cache
3336            .remember_async("expensive_async", None, || {
3337                let counter_clone = counter_clone.clone();
3338                async move {
3339                    counter_clone.fetch_add(1, std::sync::atomic::Ordering::SeqCst) as i64 + 100
3340                }
3341            })
3342            .await
3343            .unwrap();
3344        assert_eq!(val, 100);
3345
3346        // 第二次调用应命中缓存,callback 不被调用
3347        let val: i64 = cache
3348            .remember_async("expensive_async", None, || {
3349                let counter_clone = counter_clone.clone();
3350                async move {
3351                    counter_clone.fetch_add(1, std::sync::atomic::Ordering::SeqCst) as i64 + 200
3352                }
3353            })
3354            .await
3355            .unwrap();
3356        assert_eq!(val, 100);
3357
3358        assert_eq!(counter.load(std::sync::atomic::Ordering::SeqCst), 1);
3359    }
3360
3361    #[tokio::test]
3362    async fn test_cache_remember_async_cache_hit_returns_cached() {
3363        let cache = make_cache();
3364        cache.set("predefined_async", 42i64, None).unwrap();
3365
3366        let val: i64 = cache
3367            .remember_async("predefined_async", None, || async {
3368                panic!("callback should not be called on cache hit");
3369            })
3370            .await
3371            .unwrap();
3372        assert_eq!(val, 42);
3373    }
3374
3375    #[tokio::test]
3376    async fn test_cache_remember_async_writes_with_ttl() {
3377        let cache = make_cache();
3378        cache
3379            .remember_async("key_async", Some(Duration::from_millis(50)), || async {
3380                42i64
3381            })
3382            .await
3383            .unwrap();
3384
3385        assert_eq!(
3386            cache.get::<String>("key_async").unwrap(),
3387            Some("42".to_string())
3388        );
3389
3390        tokio::time::sleep(Duration::from_millis(100)).await;
3391        assert!(cache.get::<String>("key_async").unwrap().is_none());
3392    }
3393
3394    #[tokio::test]
3395    async fn test_cache_remember_async_releases_lock_on_success() {
3396        let cache = make_cache();
3397        cache
3398            .remember_async("key_async", None, || async { 42i64 })
3399            .await
3400            .unwrap();
3401        assert!(!cache.has("key_async_lock").unwrap());
3402    }
3403
3404    #[tokio::test]
3405    async fn test_cache_remember_async_lock_has_no_ttl_php_bug() {
3406        let cache = make_cache();
3407        cache
3408            .remember_async("key_async", None, || async { 42i64 })
3409            .await
3410            .unwrap();
3411        assert!(!cache.has("key_async_lock").unwrap());
3412    }
3413
3414    // ========================================================================
3415    // 组 12:Cache facade with_store(命名 store 访问)
3416    // ========================================================================
3417
3418    #[test]
3419    fn test_cache_with_store() {
3420        let cache = Cache::new();
3421        cache.register_store("redis", Box::new(MemoryCacheDriver::new()));
3422
3423        let result = cache
3424            .with_store("redis", |driver| {
3425                driver.set_raw("key", b"value".to_vec(), None)?;
3426                driver.get_raw("key")
3427            })
3428            .unwrap();
3429
3430        assert_eq!(result, Some(b"value".to_vec()));
3431    }
3432
3433    #[test]
3434    fn test_cache_with_store_not_found() {
3435        let cache = Cache::new();
3436        let result: Result<Option<Vec<u8>>, CacheError> =
3437            cache.with_store("nonexistent", |driver| driver.get_raw("key"));
3438        assert!(matches!(result, Err(CacheError::NotFound(_))));
3439    }
3440
3441    // ========================================================================
3442    // 组 13:全局 Cache facade(default_cache / init_default_cache)
3443    // ========================================================================
3444
3445    #[test]
3446    fn test_default_cache_singleton() {
3447        let c1 = default_cache();
3448        let c2 = default_cache();
3449        // 同一个全局实例
3450        assert!(std::ptr::eq(c1, c2));
3451    }
3452
3453    // 注:不测试 init_default_cache 的副作用,因为它修改全局状态,
3454    // 会影响其他测试。全局初始化应由应用入口负责。
3455
3456    // ========================================================================
3457    // 组 14:R5 PHP 行为对齐验证(硬约束)
3458    // ========================================================================
3459
3460    #[test]
3461    fn test_r5_php_set_get_basic_alignment() {
3462        // R5: PHP Cache::set + Cache::get 基本行为对齐
3463        // PHP:
3464        //   Cache::set('name', 'Alice');
3465        //   $val = Cache::get('name');  // 'Alice'
3466        let cache = make_cache();
3467        cache.set("name", "Alice", None).unwrap();
3468        let val: String = cache.get("name").unwrap().unwrap();
3469        assert_eq!(val, "Alice");
3470    }
3471
3472    #[test]
3473    fn test_r5_php_is_numeric_short_circuit() {
3474        // R5: PHP is_numeric 短路 — 数字不经过 serialize
3475        // PHP:
3476        //   Cache::set('count', 42);
3477        //   $val = Cache::get('count');  // "42" (string, PHP bug)
3478        let cache = make_cache();
3479        cache.set("count", 42i64, None).unwrap();
3480
3481        // PHP bug 复刻:get 返回 string 而非 int
3482        let s: String = cache.get("count").unwrap().unwrap();
3483        assert_eq!(s, "42");
3484    }
3485
3486    #[test]
3487    fn test_r5_php_inc_no_serialize() {
3488        // R5: PHP inc 不经序列化层 — 直接数字操作
3489        // PHP Redis: INCRBY; File: read → +step → write
3490        let cache = make_cache();
3491        cache.set("counter", 100i64, None).unwrap();
3492        let new_val = cache.inc("counter", 50).unwrap();
3493        assert_eq!(new_val, 150);
3494
3495        // 验证存储的是数字字符串
3496        let s: String = cache.get("counter").unwrap().unwrap();
3497        assert_eq!(s, "150");
3498    }
3499
3500    #[test]
3501    fn test_r5_php_dec_no_serialize() {
3502        // R5: PHP dec 不经序列化层
3503        let cache = make_cache();
3504        cache.set("counter", 100i64, None).unwrap();
3505        let new_val = cache.dec("counter", 30).unwrap();
3506        assert_eq!(new_val, 70);
3507    }
3508
3509    #[tokio::test]
3510    async fn test_r5_php_remember_lock_mechanism() {
3511        // R5: PHP remember 锁机制 — {name}_lock key + 200ms 轮询 + 5s 超时
3512        // 验证:未命中 → 调用 callback → 写入缓存 → 释放锁
3513        let cache = make_cache();
3514        let val: i64 = cache.remember("key", None, || 42).await.unwrap();
3515        assert_eq!(val, 42);
3516        assert_eq!(cache.get::<String>("key").unwrap(), Some("42".to_string()));
3517        // 锁应被释放
3518        assert!(!cache.has("key_lock").unwrap());
3519    }
3520
3521    #[test]
3522    fn test_r5_php_push_max_1000_array_shift() {
3523        // R5: PHP push 上限 1000 + array_shift
3524        let cache = make_cache();
3525        for i in 0..1001i64 {
3526            cache.push("list", i, None).unwrap();
3527        }
3528        let list: Vec<i64> = cache.get("list").unwrap().unwrap();
3529        assert_eq!(list.len(), 1000);
3530        assert_eq!(list[0], 1); // 0 被丢弃
3531        assert_eq!(list[999], 1000);
3532    }
3533
3534    #[test]
3535    fn test_r5_php_push_array_unique() {
3536        // R5: PHP push array_unique 去重
3537        let cache = make_cache();
3538        cache.push("list", "a".to_string(), None).unwrap();
3539        cache.push("list", "a".to_string(), None).unwrap();
3540        cache.push("list", "b".to_string(), None).unwrap();
3541        cache.push("list", "a".to_string(), None).unwrap();
3542
3543        let list: Vec<String> = cache.get("list").unwrap().unwrap();
3544        assert_eq!(list, vec!["a".to_string(), "b".to_string()]);
3545    }
3546
3547    #[test]
3548    fn test_r5_php_pull_get_then_delete() {
3549        // R5: PHP pull — get + delete
3550        let cache = make_cache();
3551        cache.set("key", "value", None).unwrap();
3552
3553        let val: Option<String> = cache.pull("key").unwrap();
3554        assert_eq!(val, Some("value".to_string()));
3555        assert!(!cache.has("key").unwrap());
3556    }
3557
3558    #[test]
3559    fn test_r5_php_delete_nonexistent_no_error() {
3560        // R5: PHP delete 不存在的 key 不报错
3561        let cache = make_cache();
3562        let result = cache.delete("nonexistent");
3563        assert!(result.is_ok());
3564    }
3565
3566    #[test]
3567    fn test_r5_php_has_ttl_expiration() {
3568        // R5: PHP has 检查 TTL 过期
3569        let cache = make_cache();
3570        cache
3571            .set("key", "value", Some(Duration::from_millis(50)))
3572            .unwrap();
3573        assert!(cache.has("key").unwrap());
3574
3575        std::thread::sleep(Duration::from_millis(100));
3576        assert!(!cache.has("key").unwrap());
3577    }
3578
3579    #[test]
3580    fn test_r5_php_clear_all_keys() {
3581        // R5: PHP clear 清空所有缓存
3582        let cache = make_cache();
3583        cache.set("key1", "value1", None).unwrap();
3584        cache.set("key2", "value2", None).unwrap();
3585        cache.set("key3", "value3", None).unwrap();
3586
3587        cache.clear().unwrap();
3588
3589        assert!(!cache.has("key1").unwrap());
3590        assert!(!cache.has("key2").unwrap());
3591        assert!(!cache.has("key3").unwrap());
3592    }
3593
3594    // ========================================================================
3595    // 组 15:PHP 源码行为对齐 — 关键 bug 复刻验证
3596    // ========================================================================
3597
3598    #[test]
3599    fn test_php_bug_unserialize_numeric_returns_string() {
3600        // PHP 源码 bug 复刻:unserialize 对 is_numeric 返回 string,而非 int
3601        // PHP 源码 think\cache\Driver::unserialize 第 623-630 行:
3602        //   public function unserialize($data)
3603        //   {
3604        //       if (is_numeric($data)) {
3605        //           return $data;  // ⚠️ 返回 string,而非 int
3606        //       }
3607        //       return unserialize($data);
3608        //   }
3609        //
3610        // Rust 端通过 CacheValue::Number + 泛型 T = String 复刻此行为
3611
3612        let cache = make_cache();
3613
3614        // 存入 i64 → is_numeric 短路 → CacheValue::Number("42")
3615        cache.set("count", 42i64, None).unwrap();
3616
3617        // 取出时返回 string,对齐 PHP bug
3618        let s: String = cache.get("count").unwrap().unwrap();
3619        assert_eq!(s, "42");
3620
3621        // 业务代码需自行 parse::<i64>()(对齐 PHP (int) Cache::get('count'))
3622        let n: i64 = s.parse().unwrap();
3623        assert_eq!(n, 42);
3624    }
3625
3626    #[tokio::test]
3627    async fn test_php_bug_remember_lock_no_ttl() {
3628        // PHP 源码 bug 复刻:remember 锁 key 无 TTL
3629        // PHP 源码 think\cache\Driver::remember 第 305 行:
3630        //   $this->set($lockName, 1);  // 无第三个参数 $expire
3631        //
3632        // 验证方式:检查我们的实现也使用 ttl = None(代码审查确认)
3633        // 这里通过正常路径验证锁被释放(间接验证无 TTL 锁不会卡死)
3634
3635        let cache = make_cache();
3636        cache.remember("key", None, || 42i64).await.unwrap();
3637        // 锁被正常释放(无 TTL 锁在正常路径下也会被 delete)
3638        assert!(!cache.has("key_lock").unwrap());
3639    }
3640
3641    #[tokio::test]
3642    async fn test_php_bug_remember_has_get_double_check() {
3643        // PHP 源码 bug 复刻:remember 中 has() + get() 双查(TOCTOU)
3644        // PHP 源码 think\cache\Driver::remember 第 295-298 行:
3645        //   if ($this->has($lockName)) {  // 第一次检查
3646        //       while ($this->has($lockName) && ...) {  // 循环中再次检查
3647        //           usleep(200000);
3648        //       }
3649        //       // ...
3650        //       $data = $this->get($name);  // 第二次检查(read)
3651        //   }
3652        //
3653        // Rust 端复刻此双查模式(代码审查确认):
3654        // 1. if self.has(&lock_key)?  // 第一次
3655        // 2. while self.has(&lock_key)?  // 循环
3656        // 3. if let Some(cached) = self.get::<T>(key)?  // 读
3657
3658        // 此测试验证正常路径下的双查行为(不触发死锁)
3659        let cache = make_cache();
3660        let val: i64 = cache.remember("key", None, || 42).await.unwrap();
3661        assert_eq!(val, 42);
3662    }
3663
3664    #[test]
3665    fn test_php_behavior_set_overwrite() {
3666        // PHP 行为:同 key 重复 set 覆盖旧值
3667        let cache = make_cache();
3668        cache.set("key", "first", None).unwrap();
3669        cache.set("key", "second", None).unwrap();
3670
3671        let val: String = cache.get("key").unwrap().unwrap();
3672        assert_eq!(val, "second");
3673    }
3674
3675    #[test]
3676    fn test_php_behavior_ttl_permanent() {
3677        // PHP 行为:ttl = null 永不过期
3678        let cache = make_cache();
3679        cache.set("key", "value", None).unwrap();
3680
3681        // 立即读取应命中
3682        assert!(cache.has("key").unwrap());
3683
3684        // 短暂等待后读取应仍命中(永不过期)
3685        std::thread::sleep(Duration::from_millis(50));
3686        assert!(cache.has("key").unwrap());
3687    }
3688
3689    // ========================================================================
3690    // 组 16:RedisConfig 配置(对齐 PHP think\cache\driver\Redis::$options)
3691    // ========================================================================
3692
3693    #[test]
3694    fn test_redis_config_default() {
3695        // 对齐 PHP 默认值(Redis.php 第 33-44 行)
3696        let config = RedisConfig::default();
3697        assert_eq!(config.host, "127.0.0.1");
3698        assert_eq!(config.port, 6379);
3699        assert_eq!(config.password, "");
3700        assert_eq!(config.select, 0);
3701        assert_eq!(config.timeout, Duration::ZERO);
3702        assert_eq!(config.expire, None);
3703        assert!(!config.persistent);
3704        assert_eq!(config.prefix, "");
3705        assert_eq!(config.tag_prefix, "tag:");
3706    }
3707
3708    #[test]
3709    fn test_redis_config_with_prefix() {
3710        let config = RedisConfig::with_prefix("myapp:");
3711        assert_eq!(config.prefix, "myapp:");
3712        assert_eq!(config.host, "127.0.0.1");
3713        assert_eq!(config.tag_prefix, "tag:");
3714    }
3715
3716    #[test]
3717    fn test_redis_config_with_expire() {
3718        let config = RedisConfig::with_expire(Duration::from_secs(3600));
3719        assert_eq!(config.expire, Some(Duration::from_secs(3600)));
3720        assert_eq!(config.prefix, "");
3721    }
3722
3723    // ========================================================================
3724    // 组 17:MockRedisBackend 基础 KV 操作
3725    // ========================================================================
3726
3727    #[test]
3728    fn test_mock_redis_set_get_roundtrip() {
3729        let backend = MockRedisBackend::new();
3730        backend.set("key1", b"value1".to_vec()).unwrap();
3731        let val = backend.get("key1").unwrap();
3732        assert_eq!(val, Some(b"value1".to_vec()));
3733    }
3734
3735    #[test]
3736    fn test_mock_redis_del() {
3737        let backend = MockRedisBackend::new();
3738        backend.set("key1", b"value1".to_vec()).unwrap();
3739        let removed = backend.del("key1").unwrap();
3740        assert_eq!(removed, 1);
3741        assert_eq!(backend.get("key1").unwrap(), None);
3742        // 再次删除返回 0
3743        assert_eq!(backend.del("key1").unwrap(), 0);
3744    }
3745
3746    #[test]
3747    fn test_mock_redis_exists() {
3748        let backend = MockRedisBackend::new();
3749        assert!(!backend.exists("key1").unwrap());
3750        backend.set("key1", b"value1".to_vec()).unwrap();
3751        assert!(backend.exists("key1").unwrap());
3752    }
3753
3754    #[test]
3755    fn test_mock_redis_incr_by_new_key() {
3756        // 对齐 Redis: key 不存在时初始化为 0 再 INCRBY
3757        let backend = MockRedisBackend::new();
3758        let result = backend.incr_by("counter", 5).unwrap();
3759        assert_eq!(result, 5);
3760        // 存储的是数字字符串 "5",不经 serialize
3761        let val = backend.get("counter").unwrap();
3762        assert_eq!(val, Some(b"5".to_vec()));
3763    }
3764
3765    #[test]
3766    fn test_mock_redis_incr_by_existing_key() {
3767        let backend = MockRedisBackend::new();
3768        backend.set("counter", b"10".to_vec()).unwrap();
3769        let result = backend.incr_by("counter", 5).unwrap();
3770        assert_eq!(result, 15);
3771        let val = backend.get("counter").unwrap();
3772        assert_eq!(val, Some(b"15".to_vec()));
3773    }
3774
3775    #[test]
3776    fn test_mock_redis_incr_by_non_integer_error() {
3777        // 对齐 Redis: INCRBY 对非数字值返回错误
3778        let backend = MockRedisBackend::new();
3779        backend.set("key", b"not_a_number".to_vec()).unwrap();
3780        let result = backend.incr_by("key", 1);
3781        assert!(result.is_err());
3782    }
3783
3784    #[test]
3785    fn test_mock_redis_decr_by() {
3786        let backend = MockRedisBackend::new();
3787        let result = backend.decr_by("counter", 3).unwrap();
3788        assert_eq!(result, -3);
3789    }
3790
3791    // ========================================================================
3792    // 组 18:MockRedisBackend TTL 过期
3793    // ========================================================================
3794
3795    #[test]
3796    fn test_mock_redis_set_ex_and_expire() {
3797        let backend = MockRedisBackend::new();
3798        backend
3799            .set_ex("key1", b"value1".to_vec(), Duration::from_millis(50))
3800            .unwrap();
3801        assert!(backend.get("key1").unwrap().is_some());
3802        std::thread::sleep(Duration::from_millis(80));
3803        assert_eq!(backend.get("key1").unwrap(), None);
3804    }
3805
3806    #[test]
3807    fn test_mock_redis_expired_key_exists_false() {
3808        let backend = MockRedisBackend::new();
3809        backend
3810            .set_ex("key1", b"value1".to_vec(), Duration::from_millis(50))
3811            .unwrap();
3812        assert!(backend.exists("key1").unwrap());
3813        std::thread::sleep(Duration::from_millis(80));
3814        assert!(!backend.exists("key1").unwrap());
3815    }
3816
3817    // ========================================================================
3818    // 组 19:MockRedisBackend Set 操作(对齐 Redis SADD/SMEMBERS)
3819    // ========================================================================
3820
3821    #[test]
3822    fn test_mock_redis_sadd_smembers() {
3823        let backend = MockRedisBackend::new();
3824        backend.sadd("tag:users", "user:1").unwrap();
3825        backend.sadd("tag:users", "user:2").unwrap();
3826        backend.sadd("tag:users", "user:3").unwrap();
3827        let members = backend.smembers("tag:users").unwrap();
3828        assert_eq!(members.len(), 3);
3829        assert!(members.contains(&"user:1".to_string()));
3830        assert!(members.contains(&"user:2".to_string()));
3831        assert!(members.contains(&"user:3".to_string()));
3832    }
3833
3834    #[test]
3835    fn test_mock_redis_sadd_dedup() {
3836        // 对齐 Redis SADD: 重复成员只保留一份
3837        let backend = MockRedisBackend::new();
3838        let added1 = backend.sadd("tag:users", "user:1").unwrap();
3839        assert_eq!(added1, 1);
3840        let added2 = backend.sadd("tag:users", "user:1").unwrap();
3841        assert_eq!(added2, 0);
3842        let members = backend.smembers("tag:users").unwrap();
3843        assert_eq!(members.len(), 1);
3844    }
3845
3846    #[test]
3847    fn test_mock_redis_smembers_nonexistent_key() {
3848        // 对齐 Redis: SMEMBERS 不存在的 key 返回空数组
3849        let backend = MockRedisBackend::new();
3850        let members = backend.smembers("nonexistent").unwrap();
3851        assert!(members.is_empty());
3852    }
3853
3854    // ========================================================================
3855    // 组 20:MockRedisBackend flush_db 和 del_many
3856    // ========================================================================
3857
3858    #[test]
3859    fn test_mock_redis_flush_db() {
3860        let backend = MockRedisBackend::new();
3861        backend.set("key1", b"v1".to_vec()).unwrap();
3862        backend.set("key2", b"v2".to_vec()).unwrap();
3863        backend.sadd("tag:1", "m1").unwrap();
3864        backend.flush_db().unwrap();
3865        assert_eq!(backend.get("key1").unwrap(), None);
3866        assert_eq!(backend.get("key2").unwrap(), None);
3867        assert!(backend.smembers("tag:1").unwrap().is_empty());
3868    }
3869
3870    #[test]
3871    fn test_mock_redis_del_many() {
3872        let backend = MockRedisBackend::new();
3873        backend.set("key1", b"v1".to_vec()).unwrap();
3874        backend.set("key2", b"v2".to_vec()).unwrap();
3875        backend.set("key3", b"v3".to_vec()).unwrap();
3876        let removed = backend.del_many(&["key1", "key2", "nonexistent"]).unwrap();
3877        assert_eq!(removed, 2);
3878        assert_eq!(backend.get("key1").unwrap(), None);
3879        assert_eq!(backend.get("key2").unwrap(), None);
3880        assert!(backend.get("key3").unwrap().is_some());
3881    }
3882
3883    // ========================================================================
3884    // 组 21:RedisCacheDriver 基本 API(对齐 PHP Redis 驱动)
3885    // ========================================================================
3886
3887    /// 创建带 Mock backend 的 RedisCacheDriver
3888    fn make_redis_driver() -> RedisCacheDriver {
3889        RedisCacheDriver::new(RedisConfig::default())
3890    }
3891
3892    #[test]
3893    fn test_redis_driver_set_get_roundtrip() {
3894        let driver = make_redis_driver();
3895        driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
3896        let val = driver.get_raw("key1").unwrap();
3897        assert_eq!(val, Some(b"value1".to_vec()));
3898    }
3899
3900    #[test]
3901    fn test_redis_driver_delete() {
3902        let driver = make_redis_driver();
3903        driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
3904        driver.delete("key1").unwrap();
3905        assert_eq!(driver.get_raw("key1").unwrap(), None);
3906    }
3907
3908    #[test]
3909    fn test_redis_driver_has() {
3910        let driver = make_redis_driver();
3911        assert!(!driver.has("key1").unwrap());
3912        driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
3913        assert!(driver.has("key1").unwrap());
3914    }
3915
3916    #[test]
3917    fn test_redis_driver_clear() {
3918        let driver = make_redis_driver();
3919        driver.set_raw("key1", b"v1".to_vec(), None).unwrap();
3920        driver.set_raw("key2", b"v2".to_vec(), None).unwrap();
3921        driver.clear().unwrap();
3922        assert_eq!(driver.get_raw("key1").unwrap(), None);
3923        assert_eq!(driver.get_raw("key2").unwrap(), None);
3924    }
3925
3926    #[test]
3927    fn test_redis_driver_inc_dec() {
3928        let driver = make_redis_driver();
3929        // inc 新 key(对齐 Redis INCRBY)
3930        let result = driver.inc("counter", 5).unwrap();
3931        assert_eq!(result, 5);
3932        let result = driver.inc("counter", 3).unwrap();
3933        assert_eq!(result, 8);
3934        let result = driver.dec("counter", 2).unwrap();
3935        assert_eq!(result, 6);
3936    }
3937
3938    // ========================================================================
3939    // 组 22:RedisCacheDriver key 构造(对齐 PHP getCacheKey/getTagKey)
3940    // ========================================================================
3941
3942    #[test]
3943    fn test_redis_driver_cache_key_with_prefix() {
3944        // 对齐 PHP: getCacheKey(name) = prefix + name
3945        let driver = RedisCacheDriver::new(RedisConfig::with_prefix("myapp:"));
3946        assert_eq!(driver.cache_key("user:1"), "myapp:user:1");
3947    }
3948
3949    #[test]
3950    fn test_redis_driver_cache_key_no_prefix() {
3951        let driver = RedisCacheDriver::new(RedisConfig::default());
3952        assert_eq!(driver.cache_key("user:1"), "user:1");
3953    }
3954
3955    #[test]
3956    fn test_redis_driver_tag_key_md5() {
3957        // 对齐 PHP: getTagKey(tag) = tag_prefix + md5(tag)
3958        let driver = RedisCacheDriver::new(RedisConfig::default());
3959        let tag_key = driver.tag_key("users");
3960        let expected_md5 = compute_md5("users");
3961        assert_eq!(tag_key, format!("tag:{}", expected_md5));
3962    }
3963
3964    #[test]
3965    fn test_redis_driver_tag_key_custom_prefix() {
3966        let config = RedisConfig {
3967            tag_prefix: "t:".to_string(),
3968            ..RedisConfig::default()
3969        };
3970        let driver = RedisCacheDriver::new(config);
3971        let tag_key = driver.tag_key("users");
3972        let expected_md5 = compute_md5("users");
3973        assert_eq!(tag_key, format!("t:{}", expected_md5));
3974    }
3975
3976    // ========================================================================
3977    // 组 23:RedisCacheDriver prefix 生效(对齐 PHP Redis::set/get 自动加前缀)
3978    // ========================================================================
3979
3980    #[test]
3981    fn test_redis_driver_prefix_applied_to_set() {
3982        // 对齐 PHP: set 时自动加 prefix 到 key
3983        let driver = RedisCacheDriver::new(RedisConfig::with_prefix("myapp:"));
3984        driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
3985        // 底层 backend 收到的 key 应该是 "myapp:key1"
3986        let val = driver.backend().get("myapp:key1").unwrap();
3987        assert_eq!(val, Some(b"value1".to_vec()));
3988        // 不带 prefix 的 key 应该不存在
3989        assert_eq!(driver.backend().get("key1").unwrap(), None);
3990    }
3991
3992    #[test]
3993    fn test_redis_driver_prefix_applied_to_get() {
3994        let driver = RedisCacheDriver::new(RedisConfig::with_prefix("myapp:"));
3995        driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
3996        let val = driver.get_raw("key1").unwrap();
3997        assert_eq!(val, Some(b"value1".to_vec()));
3998    }
3999
4000    #[test]
4001    fn test_redis_driver_prefix_applied_to_delete() {
4002        let driver = RedisCacheDriver::new(RedisConfig::with_prefix("myapp:"));
4003        driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
4004        driver.delete("key1").unwrap();
4005        assert_eq!(driver.backend().get("myapp:key1").unwrap(), None);
4006    }
4007
4008    #[test]
4009    fn test_redis_driver_prefix_applied_to_has() {
4010        let driver = RedisCacheDriver::new(RedisConfig::with_prefix("myapp:"));
4011        driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
4012        assert!(driver.has("key1").unwrap());
4013        assert!(driver.backend().exists("myapp:key1").unwrap());
4014    }
4015
4016    #[test]
4017    fn test_redis_driver_prefix_applied_to_inc() {
4018        let driver = RedisCacheDriver::new(RedisConfig::with_prefix("myapp:"));
4019        let result = driver.inc("counter", 5).unwrap();
4020        assert_eq!(result, 5);
4021        let val = driver.backend().get("myapp:counter").unwrap();
4022        assert_eq!(val, Some(b"5".to_vec()));
4023    }
4024
4025    // ========================================================================
4026    // 组 24:RedisCacheDriver tag 操作(对齐 PHP Redis::append/getTagItems/clearTag)
4027    // ========================================================================
4028
4029    #[test]
4030    fn test_redis_driver_append_and_get_tag_items() {
4031        // 对齐 PHP Redis::append 用 SADD
4032        let driver = make_redis_driver();
4033        driver.append("tag:users", "user:1").unwrap();
4034        driver.append("tag:users", "user:2").unwrap();
4035        driver.append("tag:users", "user:3").unwrap();
4036        let members = driver.backend().smembers("tag:users").unwrap();
4037        assert_eq!(members.len(), 3);
4038    }
4039
4040    #[test]
4041    fn test_redis_driver_get_tag_items_with_tag_key() {
4042        // 对齐 PHP: getTagItems(tag) 通过 getTagKey(tag) + getCacheKey 转换
4043        let driver = make_redis_driver();
4044        let tag_name = driver.tag_key("users");
4045        driver.append(&tag_name, "user:1").unwrap();
4046        driver.append(&tag_name, "user:2").unwrap();
4047        let members = driver.get_tag_items("users").unwrap();
4048        assert_eq!(members.len(), 2);
4049        assert!(members.contains(&"user:1".to_string()));
4050        assert!(members.contains(&"user:2".to_string()));
4051    }
4052
4053    #[test]
4054    fn test_redis_driver_clear_tag() {
4055        let driver = make_redis_driver();
4056        driver.set_raw("key1", b"v1".to_vec(), None).unwrap();
4057        driver.set_raw("key2", b"v2".to_vec(), None).unwrap();
4058        driver.clear_tag(&["key1", "key2"]).unwrap();
4059        assert_eq!(driver.get_raw("key1").unwrap(), None);
4060        assert_eq!(driver.get_raw("key2").unwrap(), None);
4061    }
4062
4063    // ========================================================================
4064    // 组 25:RedisCacheDriver TTL(对齐 PHP Redis::set 的 SETEX vs SET 行为)
4065    // ========================================================================
4066
4067    #[test]
4068    fn test_redis_driver_set_with_ttl_uses_setex() {
4069        // 对齐 PHP: expire > 0 时用 SETEX
4070        let driver = make_redis_driver();
4071        driver
4072            .set_raw("key1", b"value1".to_vec(), Some(Duration::from_millis(100)))
4073            .unwrap();
4074        assert!(driver.get_raw("key1").unwrap().is_some());
4075        std::thread::sleep(Duration::from_millis(150));
4076        assert_eq!(driver.get_raw("key1").unwrap(), None);
4077    }
4078
4079    #[test]
4080    fn test_redis_driver_set_without_ttl_uses_set() {
4081        // 对齐 PHP: expire = 0 时用 SET(永不过期)
4082        let driver = make_redis_driver();
4083        driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
4084        std::thread::sleep(Duration::from_millis(50));
4085        assert!(driver.get_raw("key1").unwrap().is_some());
4086    }
4087
4088    #[test]
4089    fn test_redis_driver_set_with_config_expire() {
4090        // 对齐 PHP: ttl = null 时用 config.expire
4091        let config = RedisConfig::with_expire(Duration::from_millis(100));
4092        let driver = RedisCacheDriver::new(config);
4093        driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
4094        assert!(driver.get_raw("key1").unwrap().is_some());
4095        std::thread::sleep(Duration::from_millis(150));
4096        assert_eq!(driver.get_raw("key1").unwrap(), None);
4097    }
4098
4099    #[test]
4100    fn test_redis_driver_set_ttl_overrides_config_expire() {
4101        // 对齐 PHP: 显式 ttl 优先于 config.expire
4102        let config = RedisConfig::with_expire(Duration::from_secs(3600));
4103        let driver = RedisCacheDriver::new(config);
4104        driver
4105            .set_raw("key1", b"value1".to_vec(), Some(Duration::from_millis(50)))
4106            .unwrap();
4107        std::thread::sleep(Duration::from_millis(80));
4108        assert_eq!(driver.get_raw("key1").unwrap(), None);
4109    }
4110
4111    // ========================================================================
4112    // 组 26:RedisCacheDriver 通过 Cache facade 使用
4113    // ========================================================================
4114
4115    #[test]
4116    fn test_redis_driver_with_cache_facade() {
4117        // 对齐 PHP: $cache = new think\Cache(); $cache->store('redis')->set(...)
4118        let cache = Cache::new();
4119        let driver = RedisCacheDriver::new(RedisConfig::default());
4120        cache.register_store("redis", Box::new(driver));
4121        cache.set_default_store("redis").unwrap();
4122        cache.set("key", "value", None).unwrap();
4123        let val: String = cache.get("key").unwrap().unwrap();
4124        assert_eq!(val, "value");
4125    }
4126
4127    #[test]
4128    fn test_redis_driver_with_cache_facade_inc() {
4129        // 通过 Cache facade 使用 Redis 驱动的 inc(不经 serialize)
4130        let cache = Cache::new();
4131        let driver = RedisCacheDriver::new(RedisConfig::default());
4132        cache.register_store("redis", Box::new(driver));
4133        cache.set_default_store("redis").unwrap();
4134        let result = cache.inc("counter", 5).unwrap();
4135        assert_eq!(result, 5);
4136        let result = cache.inc("counter", 3).unwrap();
4137        assert_eq!(result, 8);
4138    }
4139
4140    // ========================================================================
4141    // 组 27:PHP 行为对齐验证(R5 Redis 硬约束)
4142    // ========================================================================
4143
4144    #[test]
4145    fn test_php_redis_inc_not_through_serialize() {
4146        // R5-Redis-1: inc 不经 serialize(存储的是数字字符串,不是 PHP serialize 格式)
4147        // PHP Redis::inc 直接 INCRBY,File 驱动读取→加减→写回
4148        // 验证:Redis 驱动 inc 后,底层存储的是 "5"(数字字符串),
4149        //       而不是 PHP serialize 格式 "i:5;"
4150        let driver = make_redis_driver();
4151        driver.inc("counter", 5).unwrap();
4152        let val = driver.backend().get(&driver.cache_key("counter")).unwrap();
4153        assert_eq!(val, Some(b"5".to_vec())); // 数字字符串
4154        assert_ne!(val, Some(b"i:5;".to_vec())); // 不是 PHP serialize 格式
4155    }
4156
4157    #[test]
4158    fn test_php_redis_set_with_ttl_expires() {
4159        // R5-Redis-2: set 带 TTL 用 SETEX(通过 TTL 过期行为验证)
4160        let driver = make_redis_driver();
4161        driver
4162            .set_raw("key", b"value".to_vec(), Some(Duration::from_millis(50)))
4163            .unwrap();
4164        assert!(driver.get_raw("key").unwrap().is_some());
4165        std::thread::sleep(Duration::from_millis(80));
4166        assert_eq!(driver.get_raw("key").unwrap(), None);
4167    }
4168
4169    #[test]
4170    fn test_php_redis_set_without_ttl_permanent() {
4171        // R5-Redis-3: set 无 TTL 用 SET(永不过期)
4172        let driver = make_redis_driver();
4173        driver.set_raw("key", b"value".to_vec(), None).unwrap();
4174        std::thread::sleep(Duration::from_millis(50));
4175        assert!(driver.get_raw("key").unwrap().is_some());
4176    }
4177
4178    #[test]
4179    fn test_php_redis_tag_key_format() {
4180        // R5-Redis-4: tag_key = tag_prefix + md5(tag)
4181        let driver = make_redis_driver();
4182        let tag_key = driver.tag_key("users");
4183        let expected = format!("tag:{}", compute_md5("users"));
4184        assert_eq!(tag_key, expected);
4185        assert_eq!(compute_md5("users").len(), 32);
4186    }
4187
4188    #[test]
4189    fn test_php_redis_clear_uses_flushdb() {
4190        // R5-Redis-5: clear 用 FLUSHDB(清空所有 key 和 set)
4191        let driver = make_redis_driver();
4192        driver.set_raw("key1", b"v1".to_vec(), None).unwrap();
4193        driver.set_raw("key2", b"v2".to_vec(), None).unwrap();
4194        driver.append("tag:1", "m1").unwrap();
4195        driver.clear().unwrap();
4196        assert_eq!(driver.get_raw("key1").unwrap(), None);
4197        assert_eq!(driver.get_raw("key2").unwrap(), None);
4198        assert!(driver.backend().smembers("tag:1").unwrap().is_empty());
4199    }
4200
4201    #[test]
4202    fn test_php_redis_inc_returns_new_value() {
4203        // R5-Redis-6: inc 返回新值(对齐 PHP incrby 返回值)
4204        let driver = make_redis_driver();
4205        let r1 = driver.inc("c", 1).unwrap();
4206        assert_eq!(r1, 1);
4207        let r2 = driver.inc("c", 1).unwrap();
4208        assert_eq!(r2, 2);
4209        let r3 = driver.inc("c", 10).unwrap();
4210        assert_eq!(r3, 12);
4211        let r4 = driver.dec("c", 5).unwrap();
4212        assert_eq!(r4, 7);
4213    }
4214
4215    #[test]
4216    fn test_php_redis_delete_nonexistent_returns_ok() {
4217        // R5-Redis-7: delete 不存在的 key 返回 Ok
4218        let driver = make_redis_driver();
4219        driver.delete("nonexistent").unwrap();
4220    }
4221
4222    #[test]
4223    fn test_php_redis_md5_alignment() {
4224        // R5-Redis-8: md5 对齐 PHP md5() 函数
4225        // PHP: md5("hello") = "5d41402abc4b2a76b9719d911017c592"
4226        assert_eq!(compute_md5("hello"), "5d41402abc4b2a76b9719d911017c592");
4227        // PHP: md5("") = "d41d8cd98f00b204e9800998ecf8427e"
4228        assert_eq!(compute_md5(""), "d41d8cd98f00b204e9800998ecf8427e");
4229        assert_eq!(compute_md5("users").len(), 32);
4230    }
4231
4232    #[test]
4233    fn test_php_redis_append_uses_sadd() {
4234        // R5-Redis-9: append 用 SADD(Set 存储,去重)
4235        // 对比 PHP File 驱动 append 用 push(数组存储)
4236        let driver = make_redis_driver();
4237        driver.append("tag:1", "m1").unwrap();
4238        driver.append("tag:1", "m1").unwrap(); // 重复
4239        driver.append("tag:1", "m2").unwrap();
4240        let members = driver.backend().smembers("tag:1").unwrap();
4241        // SADD 去重:只有 2 个成员
4242        assert_eq!(members.len(), 2);
4243    }
4244
4245    #[test]
4246    fn test_php_redis_config_precedence_ttl() {
4247        // R5-Redis-10: TTL 优先级:显式 ttl > config.expire > None(永不过期)
4248        // 1. 显式 ttl 优先于 config.expire
4249        let config = RedisConfig::with_expire(Duration::from_secs(3600));
4250        let driver = RedisCacheDriver::new(config);
4251        driver
4252            .set_raw("key1", b"v1".to_vec(), Some(Duration::from_millis(50)))
4253            .unwrap();
4254        std::thread::sleep(Duration::from_millis(80));
4255        assert_eq!(driver.get_raw("key1").unwrap(), None); // 显式 ttl 生效
4256
4257        // 2. config.expire 优先于 None
4258        let config = RedisConfig::with_expire(Duration::from_millis(50));
4259        let driver = RedisCacheDriver::new(config);
4260        driver.set_raw("key2", b"v2".to_vec(), None).unwrap();
4261        std::thread::sleep(Duration::from_millis(80));
4262        assert_eq!(driver.get_raw("key2").unwrap(), None); // config.expire 生效
4263
4264        // 3. 都无则永不过期
4265        let driver = make_redis_driver();
4266        driver.set_raw("key3", b"v3".to_vec(), None).unwrap();
4267        std::thread::sleep(Duration::from_millis(50));
4268        assert!(driver.get_raw("key3").unwrap().is_some()); // 永不过期
4269    }
4270
4271    // ========================================================================
4272    // 组 28:MultiLevelCacheDriver 基础操作
4273    // ========================================================================
4274
4275    #[test]
4276    fn test_multi_level_driver_set_get() {
4277        let l1 = sz_rust_orm_facade::MemoryCache::new();
4278        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4279
4280        driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
4281        let val = driver.get_raw("key1").unwrap();
4282        assert_eq!(val, Some(b"value1".to_vec()));
4283    }
4284
4285    #[test]
4286    fn test_multi_level_driver_delete() {
4287        let l1 = sz_rust_orm_facade::MemoryCache::new();
4288        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4289
4290        driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
4291        driver.delete("key1").unwrap();
4292        assert_eq!(driver.get_raw("key1").unwrap(), None);
4293    }
4294
4295    #[test]
4296    fn test_multi_level_driver_has() {
4297        let l1 = sz_rust_orm_facade::MemoryCache::new();
4298        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4299
4300        assert!(!driver.has("key1").unwrap());
4301        driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
4302        assert!(driver.has("key1").unwrap());
4303    }
4304
4305    #[test]
4306    fn test_multi_level_driver_clear() {
4307        let l1 = sz_rust_orm_facade::MemoryCache::new();
4308        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4309
4310        driver.set_raw("key1", b"v1".to_vec(), None).unwrap();
4311        driver.set_raw("key2", b"v2".to_vec(), None).unwrap();
4312        driver.clear().unwrap();
4313        assert_eq!(driver.get_raw("key1").unwrap(), None);
4314        assert_eq!(driver.get_raw("key2").unwrap(), None);
4315    }
4316
4317    // ========================================================================
4318    // 组 29:MultiLevelCacheDriver 多层级联
4319    // ========================================================================
4320
4321    #[test]
4322    fn test_multi_level_two_levels_cascade_get() {
4323        // L1 空,L2 有数据 → get 应从 L2 命中并回填 L1
4324        let l1 = sz_rust_orm_facade::MemoryCache::new();
4325        let l2 = sz_rust_orm_facade::MemoryCache::new();
4326
4327        // 先在 L2 写入
4328        l2.set("key", b"from_l2".to_vec(), None).unwrap();
4329
4330        let driver = MultiLevelCacheDriver::new()
4331            .add_level(Box::new(l1.clone()))
4332            .add_level(Box::new(l2));
4333
4334        // L1 未命中,L2 命中
4335        let val = driver.get_raw("key").unwrap();
4336        assert_eq!(val, Some(b"from_l2".to_vec()));
4337
4338        // L1 应被回填
4339        let l1_val = l1.get("key").unwrap();
4340        assert_eq!(l1_val, Some(b"from_l2".to_vec()));
4341    }
4342
4343    #[test]
4344    fn test_multi_level_set_writes_all_levels() {
4345        let l1 = sz_rust_orm_facade::MemoryCache::new();
4346        let l2 = sz_rust_orm_facade::MemoryCache::new();
4347
4348        let driver = MultiLevelCacheDriver::new()
4349            .add_level(Box::new(l1.clone()))
4350            .add_level(Box::new(l2.clone()));
4351
4352        driver.set_raw("key", b"value".to_vec(), None).unwrap();
4353
4354        // 两层都应有
4355        assert_eq!(l1.get("key").unwrap(), Some(b"value".to_vec()));
4356        assert_eq!(l2.get("key").unwrap(), Some(b"value".to_vec()));
4357    }
4358
4359    #[test]
4360    fn test_multi_level_delete_removes_all_levels() {
4361        let l1 = sz_rust_orm_facade::MemoryCache::new();
4362        let l2 = sz_rust_orm_facade::MemoryCache::new();
4363
4364        let driver = MultiLevelCacheDriver::new()
4365            .add_level(Box::new(l1.clone()))
4366            .add_level(Box::new(l2.clone()));
4367
4368        driver.set_raw("key", b"value".to_vec(), None).unwrap();
4369        driver.delete("key").unwrap();
4370
4371        assert_eq!(l1.get("key").unwrap(), None);
4372        assert_eq!(l2.get("key").unwrap(), None);
4373    }
4374
4375    #[test]
4376    fn test_multi_level_l1_hit_skips_l2() {
4377        // L1 命中时不查询 L2
4378        let l1 = sz_rust_orm_facade::MemoryCache::new();
4379        let l2 = sz_rust_orm_facade::MemoryCache::new();
4380
4381        l1.set("key", b"from_l1".to_vec(), None).unwrap();
4382        l2.set("key", b"from_l2".to_vec(), None).unwrap();
4383
4384        let driver = MultiLevelCacheDriver::new()
4385            .add_level(Box::new(l1))
4386            .add_level(Box::new(l2));
4387
4388        let val = driver.get_raw("key").unwrap();
4389        assert_eq!(val, Some(b"from_l1".to_vec()));
4390    }
4391
4392    // ========================================================================
4393    // 组 30:MultiLevelCacheDriver inc/dec
4394    // ========================================================================
4395
4396    #[test]
4397    fn test_multi_level_driver_inc_initial_value() {
4398        let l1 = sz_rust_orm_facade::MemoryCache::new();
4399        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4400
4401        let new_val = driver.inc("counter", 1).unwrap();
4402        assert_eq!(new_val, 1);
4403
4404        let val = driver.get_raw("counter").unwrap();
4405        assert_eq!(val, Some(b"1".to_vec()));
4406    }
4407
4408    #[test]
4409    fn test_multi_level_driver_inc_accumulate() {
4410        let l1 = sz_rust_orm_facade::MemoryCache::new();
4411        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4412
4413        driver.inc("counter", 5).unwrap();
4414        driver.inc("counter", 3).unwrap();
4415        driver.inc("counter", 1).unwrap();
4416
4417        let val = driver.get_raw("counter").unwrap();
4418        assert_eq!(val, Some(b"9".to_vec()));
4419    }
4420
4421    #[test]
4422    fn test_multi_level_driver_dec() {
4423        let l1 = sz_rust_orm_facade::MemoryCache::new();
4424        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4425
4426        driver.set_raw("counter", b"10".to_vec(), None).unwrap();
4427        let new_val = driver.dec("counter", 3).unwrap();
4428        assert_eq!(new_val, 7);
4429
4430        let val = driver.get_raw("counter").unwrap();
4431        assert_eq!(val, Some(b"7".to_vec()));
4432    }
4433
4434    #[test]
4435    fn test_multi_level_driver_inc_preserves_ttl() {
4436        // inc/dec 应保留原 TTL
4437        let l1 = sz_rust_orm_facade::MemoryCache::new();
4438        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4439
4440        driver
4441            .set_raw("counter", b"5".to_vec(), Some(Duration::from_millis(200)))
4442            .unwrap();
4443
4444        // TTL 存在
4445        let ttl_before = driver.inner().ttl("counter").unwrap();
4446        assert!(ttl_before.is_some());
4447
4448        driver.inc("counter", 1).unwrap();
4449
4450        // TTL 应被保留
4451        let ttl_after = driver.inner().ttl("counter").unwrap();
4452        assert!(ttl_after.is_some());
4453    }
4454
4455    // ========================================================================
4456    // 组 31:MultiLevelCacheDriver TTL 过期
4457    // ========================================================================
4458
4459    #[test]
4460    fn test_multi_level_driver_ttl_expiration() {
4461        let l1 = sz_rust_orm_facade::MemoryCache::new();
4462        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4463
4464        driver
4465            .set_raw("key", b"value".to_vec(), Some(Duration::from_millis(50)))
4466            .unwrap();
4467        assert!(driver.get_raw("key").unwrap().is_some());
4468
4469        std::thread::sleep(Duration::from_millis(80));
4470        assert_eq!(driver.get_raw("key").unwrap(), None);
4471    }
4472
4473    #[test]
4474    fn test_multi_level_driver_has_checks_ttl() {
4475        let l1 = sz_rust_orm_facade::MemoryCache::new();
4476        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4477
4478        driver
4479            .set_raw("key", b"value".to_vec(), Some(Duration::from_millis(50)))
4480            .unwrap();
4481        assert!(driver.has("key").unwrap());
4482
4483        std::thread::sleep(Duration::from_millis(80));
4484        assert!(!driver.has("key").unwrap());
4485    }
4486
4487    // ========================================================================
4488    // 组 32:MultiLevelCacheDriver 通过 Cache facade 使用
4489    // ========================================================================
4490
4491    #[test]
4492    fn test_multi_level_driver_with_cache_facade() {
4493        let l1 = sz_rust_orm_facade::MemoryCache::new();
4494        let l2 = sz_rust_orm_facade::MemoryCache::new();
4495        let driver = MultiLevelCacheDriver::new()
4496            .add_level(Box::new(l1))
4497            .add_level(Box::new(l2));
4498
4499        let cache = Cache::new();
4500        cache.register_store("default", Box::new(driver));
4501
4502        cache.set("user:1", "Alice", None).unwrap();
4503        assert_eq!(
4504            cache.get::<String>("user:1").unwrap(),
4505            Some("Alice".to_string())
4506        );
4507
4508        cache.delete("user:1").unwrap();
4509        assert_eq!(cache.get::<String>("user:1").unwrap(), None);
4510    }
4511
4512    #[test]
4513    fn test_multi_level_driver_with_cache_facade_inc() {
4514        let l1 = sz_rust_orm_facade::MemoryCache::new();
4515        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4516
4517        let cache = Cache::new();
4518        cache.register_store("default", Box::new(driver));
4519
4520        cache.inc("counter", 5).unwrap();
4521        cache.inc("counter", 3).unwrap();
4522
4523        // PHP bug 复刻:inc 不经 serialize,存储为字符串 "8"
4524        // get::<String> 返回 "8"
4525        let val = cache.get::<String>("counter").unwrap();
4526        assert_eq!(val, Some("8".to_string()));
4527    }
4528
4529    // ========================================================================
4530    // 组 33:MultiLevelCacheDriver 边界情况
4531    // ========================================================================
4532
4533    #[test]
4534    fn test_multi_level_driver_empty_levels_get_returns_none() {
4535        // 无任何层级的驱动,get 返回 None(不报错)
4536        let driver = MultiLevelCacheDriver::new();
4537        assert_eq!(driver.get_raw("key").unwrap(), None);
4538    }
4539
4540    #[test]
4541    fn test_multi_level_driver_empty_levels_has_returns_false() {
4542        let driver = MultiLevelCacheDriver::new();
4543        assert!(!driver.has("key").unwrap());
4544    }
4545
4546    #[test]
4547    fn test_multi_level_driver_inc_non_numeric_value_resets_to_step() {
4548        // 非 numeric value 时,parse 失败降级为 0,再 +step
4549        let l1 = sz_rust_orm_facade::MemoryCache::new();
4550        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4551
4552        driver
4553            .set_raw("counter", b"not_a_number".to_vec(), None)
4554            .unwrap();
4555        let new_val = driver.inc("counter", 5).unwrap();
4556        assert_eq!(new_val, 5);
4557    }
4558
4559    #[test]
4560    fn test_multi_level_driver_default_impl() {
4561        // Default::default() 等价于 new()
4562        let driver = MultiLevelCacheDriver::default();
4563        assert_eq!(driver.get_raw("key").unwrap(), None);
4564    }
4565
4566    // ========================================================================
4567    // 组 34:R5 PHP 行为对齐验证(多级缓存)
4568    // ========================================================================
4569
4570    #[test]
4571    fn test_r5_multi_level_get_set_basic() {
4572        // R5: 基本 set/get 行为对齐 PHP Cache::set/get
4573        let l1 = sz_rust_orm_facade::MemoryCache::new();
4574        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4575
4576        driver.set_raw("key", b"value".to_vec(), None).unwrap();
4577        assert_eq!(driver.get_raw("key").unwrap(), Some(b"value".to_vec()));
4578    }
4579
4580    #[test]
4581    fn test_r5_multi_level_delete_nonexistent_no_error() {
4582        // R5: 删除不存在的 key 不报错
4583        let l1 = sz_rust_orm_facade::MemoryCache::new();
4584        let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4585
4586        assert!(driver.delete("nonexistent").is_ok());
4587    }
4588
4589    #[test]
4590    fn test_r5_multi_level_clear_empties_all() {
4591        // R5: clear 清空所有层
4592        let l1 = sz_rust_orm_facade::MemoryCache::new();
4593        let l2 = sz_rust_orm_facade::MemoryCache::new();
4594        let driver = MultiLevelCacheDriver::new()
4595            .add_level(Box::new(l1))
4596            .add_level(Box::new(l2));
4597
4598        driver.set_raw("k1", b"v1".to_vec(), None).unwrap();
4599        driver.set_raw("k2", b"v2".to_vec(), None).unwrap();
4600        driver.clear().unwrap();
4601
4602        assert_eq!(driver.get_raw("k1").unwrap(), None);
4603        assert_eq!(driver.get_raw("k2").unwrap(), None);
4604    }
4605
4606    #[test]
4607    fn test_r5_multi_level_cascade_fill_back() {
4608        // R5: 多级查询命中后回填低层(带 TTL 保留)
4609        let l1 = sz_rust_orm_facade::MemoryCache::new();
4610        let l2 = sz_rust_orm_facade::MemoryCache::new();
4611
4612        // L2 有数据,L1 无
4613        l2.set("key", b"from_l2".to_vec(), None).unwrap();
4614
4615        let driver = MultiLevelCacheDriver::new()
4616            .add_level(Box::new(l1.clone()))
4617            .add_level(Box::new(l2));
4618
4619        // get 触发回填
4620        let val = driver.get_raw("key").unwrap();
4621        assert_eq!(val, Some(b"from_l2".to_vec()));
4622
4623        // L1 应被回填
4624        assert_eq!(l1.get("key").unwrap(), Some(b"from_l2".to_vec()));
4625    }
4626
4627    // ========================================================================
4628    // 测试组 35: CacheDriver tag trait 默认实现(MemoryCacheDriver)
4629    // ========================================================================
4630
4631    #[test]
4632    fn test_tag_get_cache_key_default_no_prefix() {
4633        // 默认 get_cache_key 不应用前缀
4634        let driver = MemoryCacheDriver::new();
4635        assert_eq!(driver.get_cache_key("user:1"), "user:1");
4636        assert_eq!(driver.get_cache_key("hello"), "hello");
4637    }
4638
4639    #[test]
4640    fn test_tag_get_tag_key_default_format() {
4641        // 默认 get_tag_key = "tag:" + md5(tag)
4642        let driver = MemoryCacheDriver::new();
4643        let tag_key = driver.get_tag_key("user");
4644        // md5("user") = "ee11cbb19052e40b07aac0ca060c23ee"
4645        assert_eq!(tag_key, "tag:ee11cbb19052e40b07aac0ca060c23ee");
4646    }
4647
4648    #[test]
4649    fn test_tag_append_creates_new_tag_set() {
4650        // tag_append 首次调用创建空数组 + 追加
4651        let driver = MemoryCacheDriver::new();
4652        driver.tag_append("tag:abc123", "user:1").unwrap();
4653        // 直接验证存储(tag_append 第一个参数是 tag_key,存储在 get_cache_key(tag_key) 位置)
4654        let storage_key = "tag:abc123"; // get_cache_key("tag:abc123") = "tag:abc123" (no prefix)
4655        let raw = driver.get_raw(storage_key).unwrap();
4656        let stored: Vec<String> = serde_json::from_slice(&raw.unwrap()).unwrap();
4657        assert_eq!(stored, vec!["user:1"]);
4658    }
4659
4660    #[test]
4661    fn test_tag_append_appends_to_existing() {
4662        let driver = MemoryCacheDriver::new();
4663        driver.tag_append("tag:abc", "key1").unwrap();
4664        driver.tag_append("tag:abc", "key2").unwrap();
4665        let storage_key = "tag:abc";
4666        let raw = driver.get_raw(storage_key).unwrap();
4667        let stored: Vec<String> = serde_json::from_slice(&raw.unwrap()).unwrap();
4668        assert_eq!(stored, vec!["key1", "key2"]);
4669    }
4670
4671    #[test]
4672    fn test_tag_append_dedup() {
4673        // 对齐 PHP array_unique:重复值只保留首次出现
4674        let driver = MemoryCacheDriver::new();
4675        driver.tag_append("tag:abc", "key1").unwrap();
4676        driver.tag_append("tag:abc", "key1").unwrap(); // 重复
4677        let storage_key = "tag:abc";
4678        let raw = driver.get_raw(storage_key).unwrap();
4679        let stored: Vec<String> = serde_json::from_slice(&raw.unwrap()).unwrap();
4680        assert_eq!(stored, vec!["key1"]);
4681    }
4682
4683    #[test]
4684    fn test_tag_append_max_1000_cap() {
4685        // 对齐 PHP: count > 1000 时 array_shift(FIFO 丢弃最旧)
4686        let driver = MemoryCacheDriver::new();
4687        for i in 0..1001i64 {
4688            driver.tag_append("tag:abc", &format!("key{}", i)).unwrap();
4689        }
4690        let storage_key = "tag:abc";
4691        let raw = driver.get_raw(storage_key).unwrap();
4692        let stored: Vec<String> = serde_json::from_slice(&raw.unwrap()).unwrap();
4693        // 上限 1000,丢弃 key0
4694        assert_eq!(stored.len(), 1000);
4695        assert!(!stored.contains(&"key0".to_string()));
4696        assert!(stored.contains(&"key1".to_string()));
4697        assert!(stored.contains(&"key1000".to_string()));
4698    }
4699
4700    #[test]
4701    fn test_tag_items_empty_returns_empty() {
4702        let driver = MemoryCacheDriver::new();
4703        let items = driver.tag_items("nonexistent_tag").unwrap();
4704        assert!(items.is_empty());
4705    }
4706
4707    #[test]
4708    fn test_tag_items_returns_stored_keys() {
4709        let driver = MemoryCacheDriver::new();
4710        // tag_items 内部计算 get_tag_key("mytag") = "tag:" + md5("mytag")
4711        let tag_key = driver.get_tag_key("mytag");
4712        driver.tag_append(&tag_key, "key1").unwrap();
4713        driver.tag_append(&tag_key, "key2").unwrap();
4714        let items = driver.tag_items("mytag").unwrap();
4715        assert_eq!(items, vec!["key1", "key2"]);
4716    }
4717
4718    #[test]
4719    fn test_tag_clear_deletes_keys() {
4720        let driver = MemoryCacheDriver::new();
4721        // 写入两个缓存 key
4722        driver.set_raw("key1", b"v1".to_vec(), None).unwrap();
4723        driver.set_raw("key2", b"v2".to_vec(), None).unwrap();
4724        // tag_clear 删除这些 key(无前缀驱动,key = name)
4725        driver
4726            .tag_clear(&["key1".to_string(), "key2".to_string()])
4727            .unwrap();
4728        assert!(!driver.has("key1").unwrap());
4729        assert!(!driver.has("key2").unwrap());
4730    }
4731
4732    #[test]
4733    fn test_tag_clear_empty_no_error() {
4734        let driver = MemoryCacheDriver::new();
4735        // 空列表不报错
4736        driver.tag_clear(&[]).unwrap();
4737    }
4738
4739    // ========================================================================
4740    // 测试组 36: RedisCacheDriver tag trait 重写
4741    // ========================================================================
4742
4743    #[test]
4744    fn test_redis_tag_get_cache_key_with_prefix() {
4745        let config = RedisConfig {
4746            prefix: "myapp:".to_string(),
4747            ..RedisConfig::default()
4748        };
4749        let driver = RedisCacheDriver::new(config);
4750        assert_eq!(driver.get_cache_key("user:1"), "myapp:user:1");
4751    }
4752
4753    #[test]
4754    fn test_redis_tag_get_tag_key_with_tag_prefix() {
4755        let config = RedisConfig {
4756            tag_prefix: "tag:".to_string(),
4757            ..RedisConfig::default()
4758        };
4759        let driver = RedisCacheDriver::new(config);
4760        let tag_key = driver.get_tag_key("user");
4761        // md5("user") = "ee11cbb19052e40b07aac0ca060c23ee"
4762        assert_eq!(tag_key, "tag:ee11cbb19052e40b07aac0ca060c23ee");
4763    }
4764
4765    #[test]
4766    fn test_redis_tag_get_tag_key_custom_prefix() {
4767        let config = RedisConfig {
4768            tag_prefix: "t:".to_string(),
4769            ..RedisConfig::default()
4770        };
4771        let driver = RedisCacheDriver::new(config);
4772        let tag_key = driver.get_tag_key("user");
4773        assert_eq!(tag_key, "t:ee11cbb19052e40b07aac0ca060c23ee");
4774    }
4775
4776    #[test]
4777    fn test_redis_tag_append_uses_sadd() {
4778        // Redis tag_append 用 sAdd(Set 语义),而非 push(Array 语义)
4779        let driver = RedisCacheDriver::new(RedisConfig::default());
4780        let tag_key = driver.get_tag_key("mytag");
4781        driver.tag_append(&tag_key, "key1").unwrap();
4782        driver.tag_append(&tag_key, "key2").unwrap();
4783        driver.tag_append(&tag_key, "key1").unwrap(); // 重复(Set 自动去重)
4784        let items = driver.tag_items("mytag").unwrap();
4785        // Set 去重,只有 2 个元素
4786        assert_eq!(items.len(), 2);
4787        assert!(items.contains(&"key1".to_string()));
4788        assert!(items.contains(&"key2".to_string()));
4789    }
4790
4791    #[test]
4792    fn test_redis_tag_items_uses_smembers() {
4793        let driver = RedisCacheDriver::new(RedisConfig::default());
4794        let tag_key = driver.get_tag_key("mytag");
4795        driver.tag_append(&tag_key, "a").unwrap();
4796        driver.tag_append(&tag_key, "b").unwrap();
4797        driver.tag_append(&tag_key, "c").unwrap();
4798        let items = driver.tag_items("mytag").unwrap();
4799        assert_eq!(items.len(), 3);
4800    }
4801
4802    #[test]
4803    fn test_redis_tag_clear_does_not_double_prefix() {
4804        // tag_clear 接收已前缀化的 key,不得再次应用 getCacheKey
4805        let config = RedisConfig {
4806            prefix: "app:".to_string(),
4807            ..RedisConfig::default()
4808        };
4809        let driver = RedisCacheDriver::new(config);
4810        // 写入缓存(set_raw 应用前缀 → "app:key1")
4811        driver.set_raw("key1", b"v1".to_vec(), None).unwrap();
4812        // tag_items 返回 "app:key1"(已前缀化)
4813        let tag_key = driver.get_tag_key("mytag");
4814        driver.tag_append(&tag_key, "app:key1").unwrap();
4815        let items = driver.tag_items("mytag").unwrap();
4816        assert_eq!(items, vec!["app:key1"]);
4817        // tag_clear 应删除 "app:key1"(raw del),不是 "app:app:key1"
4818        driver.tag_clear(&items).unwrap();
4819        assert!(!driver.has("key1").unwrap());
4820    }
4821
4822    #[test]
4823    fn test_redis_tag_clear_empty_no_error() {
4824        let driver = RedisCacheDriver::new(RedisConfig::default());
4825        driver.tag_clear(&[]).unwrap();
4826    }
4827
4828    // ========================================================================
4829    // 测试组 37: TagSet with MemoryCacheDriver
4830    // ========================================================================
4831
4832    #[test]
4833    fn test_tagset_set_stores_value_and_appends_tag() {
4834        let cache = Cache::new();
4835        cache.register_default(MemoryCacheDriver::new());
4836
4837        // TagSet::set = cache.set + append
4838        cache.tag("user").set("user:1", "Alice", None).unwrap();
4839
4840        // 缓存值已写入
4841        assert_eq!(
4842            cache.get::<String>("user:1").unwrap(),
4843            Some("Alice".to_string())
4844        );
4845
4846        // 标签已记录 key
4847        let mgr = cache.manager.read();
4848        let driver = mgr.default_store().unwrap();
4849        let items = driver.tag_items("user").unwrap();
4850        assert_eq!(items, vec!["user:1"]);
4851    }
4852
4853    #[test]
4854    fn test_tagset_set_multiple_keys_same_tag() {
4855        let cache = Cache::new();
4856        cache.register_default(MemoryCacheDriver::new());
4857
4858        cache.tag("user").set("user:1", "Alice", None).unwrap();
4859        cache.tag("user").set("user:2", "Bob", None).unwrap();
4860        cache.tag("user").set("user:3", "Carol", None).unwrap();
4861
4862        let mgr = cache.manager.read();
4863        let driver = mgr.default_store().unwrap();
4864        let items = driver.tag_items("user").unwrap();
4865        assert_eq!(items, vec!["user:1", "user:2", "user:3"]);
4866    }
4867
4868    #[test]
4869    fn test_tagset_clear_deletes_all_tagged_keys() {
4870        let cache = Cache::new();
4871        cache.register_default(MemoryCacheDriver::new());
4872
4873        cache.tag("user").set("user:1", "Alice", None).unwrap();
4874        cache.tag("user").set("user:2", "Bob", None).unwrap();
4875        cache.tag("user").set("user:3", "Carol", None).unwrap();
4876
4877        // clear 删除所有标签下的缓存
4878        cache.tag("user").clear().unwrap();
4879
4880        assert!(cache.get::<String>("user:1").unwrap().is_none());
4881        assert!(cache.get::<String>("user:2").unwrap().is_none());
4882        assert!(cache.get::<String>("user:3").unwrap().is_none());
4883    }
4884
4885    #[test]
4886    fn test_tagset_clear_deletes_tag_key() {
4887        let cache = Cache::new();
4888        cache.register_default(MemoryCacheDriver::new());
4889
4890        cache.tag("user").set("user:1", "Alice", None).unwrap();
4891
4892        // 验证 tag key 存在
4893        let mgr = cache.manager.read();
4894        let driver = mgr.default_store().unwrap();
4895        let tag_key = driver.get_tag_key("user");
4896        assert!(driver.has(&tag_key).unwrap());
4897        drop(mgr);
4898
4899        cache.tag("user").clear().unwrap();
4900
4901        // tag key 本身也被删除
4902        let mgr = cache.manager.read();
4903        let driver = mgr.default_store().unwrap();
4904        assert!(!driver.has(&tag_key).unwrap());
4905    }
4906
4907    #[test]
4908    fn test_tagset_clear_empty_tag_no_error() {
4909        let cache = Cache::new();
4910        cache.register_default(MemoryCacheDriver::new());
4911
4912        // 没有写入任何缓存,clear 不报错
4913        cache.tag("empty").clear().unwrap();
4914    }
4915
4916    #[test]
4917    fn test_tagset_append_adds_key_to_tag() {
4918        let cache = Cache::new();
4919        cache.register_default(MemoryCacheDriver::new());
4920
4921        // 先写入缓存(不经 TagSet)
4922        cache.set("user:1", "Alice", None).unwrap();
4923        // 然后手动 append 到标签
4924        cache.tag("user").append("user:1").unwrap();
4925
4926        let mgr = cache.manager.read();
4927        let driver = mgr.default_store().unwrap();
4928        let items = driver.tag_items("user").unwrap();
4929        assert_eq!(items, vec!["user:1"]);
4930    }
4931
4932    #[test]
4933    fn test_tagset_many_tags_single_key() {
4934        let cache = Cache::new();
4935        cache.register_default(MemoryCacheDriver::new());
4936
4937        // 多标签:key 同时属于 user 和 admin
4938        cache
4939            .tag_many(&["user", "admin"])
4940            .set("key1", "val", None)
4941            .unwrap();
4942
4943        // 两个标签都应包含 key1
4944        let mgr = cache.manager.read();
4945        let driver = mgr.default_store().unwrap();
4946        let user_items = driver.tag_items("user").unwrap();
4947        let admin_items = driver.tag_items("admin").unwrap();
4948        assert_eq!(user_items, vec!["key1"]);
4949        assert_eq!(admin_items, vec!["key1"]);
4950    }
4951
4952    #[test]
4953    fn test_tagset_many_tags_clear_one() {
4954        let cache = Cache::new();
4955        cache.register_default(MemoryCacheDriver::new());
4956
4957        cache
4958            .tag_many(&["user", "admin"])
4959            .set("key1", "val", None)
4960            .unwrap();
4961
4962        // 清除 user 标签
4963        cache.tag("user").clear().unwrap();
4964
4965        // key1 被删除
4966        assert!(cache.get::<String>("key1").unwrap().is_none());
4967
4968        // admin 标签的 tag_items 仍有 key1(但 key1 已被删除)
4969        // 这是 PHP 的行为:clear 只清除 tag 下记录的 key,不清理其他 tag 的记录
4970        let mgr = cache.manager.read();
4971        let driver = mgr.default_store().unwrap();
4972        let admin_items = driver.tag_items("admin").unwrap();
4973        assert_eq!(admin_items, vec!["key1"]); // 记录仍在,但 key1 已被删
4974                                               // user 的 tag key 被删除
4975        let user_tag_key = driver.get_tag_key("user");
4976        assert!(!driver.has(&user_tag_key).unwrap());
4977    }
4978
4979    #[test]
4980    fn test_tagset_tags_getter() {
4981        let cache = Cache::new();
4982        let ts = cache.tag_many(&["a", "b", "c"]);
4983        assert_eq!(ts.tags(), &["a", "b", "c"]);
4984    }
4985
4986    // ========================================================================
4987    // 测试组 38: TagSet with RedisCacheDriver
4988    // ========================================================================
4989
4990    #[test]
4991    fn test_redis_tagset_set_stores_value_and_appends_tag() {
4992        let cache = Cache::new();
4993        let driver = RedisCacheDriver::new(RedisConfig::default());
4994        cache.register_store("redis", Box::new(driver));
4995
4996        cache.tag("user").set("user:1", "Alice", None).unwrap();
4997
4998        // 缓存值已写入
4999        assert_eq!(
5000            cache.get::<String>("user:1").unwrap(),
5001            Some("Alice".to_string())
5002        );
5003
5004        // 标签已记录 key(Redis Set 语义)
5005        let mgr = cache.manager.read();
5006        let driver = mgr.default_store().unwrap();
5007        let items = driver.tag_items("user").unwrap();
5008        assert_eq!(items, vec!["user:1"]);
5009    }
5010
5011    #[test]
5012    fn test_redis_tagset_set_with_prefix() {
5013        let cache = Cache::new();
5014        let config = RedisConfig {
5015            prefix: "app:".to_string(),
5016            ..RedisConfig::default()
5017        };
5018        let driver = RedisCacheDriver::new(config);
5019        cache.register_store("redis", Box::new(driver));
5020
5021        cache.tag("user").set("user:1", "Alice", None).unwrap();
5022
5023        // 验证 tag_items 返回已前缀化的 key
5024        let mgr = cache.manager.read();
5025        let driver = mgr.default_store().unwrap();
5026        let items = driver.tag_items("user").unwrap();
5027        assert_eq!(items, vec!["app:user:1"]);
5028    }
5029
5030    #[test]
5031    fn test_redis_tagset_clear_deletes_all_tagged_keys() {
5032        let cache = Cache::new();
5033        let driver = RedisCacheDriver::new(RedisConfig::default());
5034        cache.register_store("redis", Box::new(driver));
5035
5036        cache.tag("user").set("user:1", "Alice", None).unwrap();
5037        cache.tag("user").set("user:2", "Bob", None).unwrap();
5038        cache.tag("user").set("user:3", "Carol", None).unwrap();
5039
5040        cache.tag("user").clear().unwrap();
5041
5042        assert!(cache.get::<String>("user:1").unwrap().is_none());
5043        assert!(cache.get::<String>("user:2").unwrap().is_none());
5044        assert!(cache.get::<String>("user:3").unwrap().is_none());
5045    }
5046
5047    #[test]
5048    fn test_redis_tagset_clear_deletes_tag_key() {
5049        let cache = Cache::new();
5050        let driver = RedisCacheDriver::new(RedisConfig::default());
5051        cache.register_store("redis", Box::new(driver));
5052
5053        cache.tag("user").set("user:1", "Alice", None).unwrap();
5054
5055        let mgr = cache.manager.read();
5056        let driver = mgr.default_store().unwrap();
5057        let tag_key = driver.get_tag_key("user");
5058        // tag key 存在于 Redis backend
5059        assert!(driver.has(&tag_key).unwrap());
5060        drop(mgr);
5061
5062        cache.tag("user").clear().unwrap();
5063
5064        let mgr = cache.manager.read();
5065        let driver = mgr.default_store().unwrap();
5066        assert!(!driver.has(&tag_key).unwrap());
5067    }
5068
5069    #[test]
5070    fn test_redis_tagset_many_tags() {
5071        let cache = Cache::new();
5072        let driver = RedisCacheDriver::new(RedisConfig::default());
5073        cache.register_store("redis", Box::new(driver));
5074
5075        cache
5076            .tag_many(&["user", "admin"])
5077            .set("key1", "val", None)
5078            .unwrap();
5079
5080        let mgr = cache.manager.read();
5081        let driver = mgr.default_store().unwrap();
5082        let user_items = driver.tag_items("user").unwrap();
5083        let admin_items = driver.tag_items("admin").unwrap();
5084        assert_eq!(user_items, vec!["key1"]);
5085        assert_eq!(admin_items, vec!["key1"]);
5086    }
5087
5088    // ========================================================================
5089    // 测试组 39: R5 PHP 行为对齐
5090    // ========================================================================
5091
5092    #[test]
5093    fn test_r5_php_tag_set_then_clear() {
5094        // R5: 对齐 PHP Cache::tag('user')->set() + Cache::tag('user')->clear()
5095        let cache = Cache::new();
5096        cache.register_default(MemoryCacheDriver::new());
5097
5098        cache.tag("user").set("u1", "Alice", None).unwrap();
5099        cache.tag("user").set("u2", "Bob", None).unwrap();
5100
5101        // 非标签缓存不受影响
5102        cache.set("other", "data", None).unwrap();
5103
5104        cache.tag("user").clear().unwrap();
5105
5106        // 标签缓存被清除
5107        assert!(cache.get::<String>("u1").unwrap().is_none());
5108        assert!(cache.get::<String>("u2").unwrap().is_none());
5109        // 非标签缓存保留
5110        assert_eq!(
5111            cache.get::<String>("other").unwrap(),
5112            Some("data".to_string())
5113        );
5114    }
5115
5116    #[test]
5117    fn test_r5_php_tag_multiple_tags_clear() {
5118        // R5: 对齐 PHP 多标签场景
5119        let cache = Cache::new();
5120        cache.register_default(MemoryCacheDriver::new());
5121
5122        // key1 属于 user + admin
5123        cache
5124            .tag_many(&["user", "admin"])
5125            .set("key1", "v1", None)
5126            .unwrap();
5127        // key2 仅属于 user
5128        cache.tag("user").set("key2", "v2", None).unwrap();
5129
5130        // 清除 user 标签(key1 和 key2 都被删除)
5131        cache.tag("user").clear().unwrap();
5132
5133        assert!(cache.get::<String>("key1").unwrap().is_none());
5134        assert!(cache.get::<String>("key2").unwrap().is_none());
5135    }
5136
5137    #[test]
5138    fn test_r5_php_tag_get_cache_key_prefix() {
5139        // R5: 对齐 PHP getCacheKey — MemoryCacheDriver 无前缀
5140        let cache = Cache::new();
5141        cache.register_default(MemoryCacheDriver::new());
5142        let mgr = cache.manager.read();
5143        let driver = mgr.default_store().unwrap();
5144        assert_eq!(driver.get_cache_key("test"), "test");
5145    }
5146
5147    #[test]
5148    fn test_r5_php_tag_get_tag_key_md5() {
5149        // R5: 对齐 PHP getTagKey — tag_prefix + md5(tag)
5150        let cache = Cache::new();
5151        cache.register_default(MemoryCacheDriver::new());
5152        let mgr = cache.manager.read();
5153        let driver = mgr.default_store().unwrap();
5154        // md5("hello") = "5d41402abc4b2a76b9719d911017c592"
5155        assert_eq!(
5156            driver.get_tag_key("hello"),
5157            "tag:5d41402abc4b2a76b9719d911017c592"
5158        );
5159    }
5160
5161    #[test]
5162    fn test_r5_php_tag_push_max_1000_array_shift() {
5163        // R5: 对齐 PHP push 上限 1000 + array_shift(FIFO 丢弃最旧)
5164        let driver = MemoryCacheDriver::new();
5165        for i in 0..1005i64 {
5166            driver.tag_append("tag:test", &format!("key{}", i)).unwrap();
5167        }
5168        let storage_key = "tag:test";
5169        let raw = driver.get_raw(storage_key).unwrap();
5170        let stored: Vec<String> = serde_json::from_slice(&raw.unwrap()).unwrap();
5171        // 上限 1000
5172        assert_eq!(stored.len(), 1000);
5173        // key0~key4 被丢弃
5174        assert!(!stored.contains(&"key0".to_string()));
5175        assert!(!stored.contains(&"key4".to_string()));
5176        // key5~key1004 保留
5177        assert!(stored.contains(&"key5".to_string()));
5178        assert!(stored.contains(&"key1004".to_string()));
5179    }
5180
5181    #[test]
5182    fn test_r5_php_tag_push_array_unique() {
5183        // R5: 对齐 PHP array_unique — 去重保留首次出现
5184        let driver = MemoryCacheDriver::new();
5185        driver.tag_append("tag:u", "a").unwrap();
5186        driver.tag_append("tag:u", "b").unwrap();
5187        driver.tag_append("tag:u", "a").unwrap(); // 重复
5188        driver.tag_append("tag:u", "c").unwrap();
5189        driver.tag_append("tag:u", "b").unwrap(); // 重复
5190
5191        let storage_key = "tag:u";
5192        let raw = driver.get_raw(storage_key).unwrap();
5193        let stored: Vec<String> = serde_json::from_slice(&raw.unwrap()).unwrap();
5194        // 去重后 a, b, c(保留首次出现顺序)
5195        assert_eq!(stored, vec!["a", "b", "c"]);
5196    }
5197
5198    #[test]
5199    fn test_r5_php_tag_singleton_equivalent() {
5200        // R5: 对齐 PHP tag() 单例 — 多次调用行为一致
5201        let cache = Cache::new();
5202        cache.register_default(MemoryCacheDriver::new());
5203
5204        // 第一次调用 tag("user")
5205        cache.tag("user").set("u1", "Alice", None).unwrap();
5206        // 第二次调用 tag("user") — PHP 返回同一个 TagSet 单例
5207        cache.tag("user").set("u2", "Bob", None).unwrap();
5208
5209        // 两次 set 的 key 都在同一标签下
5210        let mgr = cache.manager.read();
5211        let driver = mgr.default_store().unwrap();
5212        let items = driver.tag_items("user").unwrap();
5213        assert_eq!(items, vec!["u1", "u2"]);
5214
5215        // clear 一次清除所有
5216        cache.tag("user").clear().unwrap();
5217        assert!(cache.get::<String>("u1").unwrap().is_none());
5218        assert!(cache.get::<String>("u2").unwrap().is_none());
5219    }
5220
5221    #[test]
5222    fn test_r5_php_tag_clear_then_set_again() {
5223        // R5: clear 后可以重新 set
5224        let cache = Cache::new();
5225        cache.register_default(MemoryCacheDriver::new());
5226
5227        cache.tag("user").set("u1", "Alice", None).unwrap();
5228        cache.tag("user").clear().unwrap();
5229        assert!(cache.get::<String>("u1").unwrap().is_none());
5230
5231        // 重新 set
5232        cache.tag("user").set("u1", "Alice2", None).unwrap();
5233        assert_eq!(
5234            cache.get::<String>("u1").unwrap(),
5235            Some("Alice2".to_string())
5236        );
5237
5238        // tag items 只包含重新 set 后的 key
5239        let mgr = cache.manager.read();
5240        let driver = mgr.default_store().unwrap();
5241        let items = driver.tag_items("user").unwrap();
5242        assert_eq!(items, vec!["u1"]);
5243    }
5244
5245    #[test]
5246    fn test_r5_php_tag_redis_set_then_clear() {
5247        // R5: Redis 驱动 tag set + clear 对齐 PHP
5248        let cache = Cache::new();
5249        let driver = RedisCacheDriver::new(RedisConfig::default());
5250        cache.register_store("redis", Box::new(driver));
5251
5252        cache.tag("article").set("a:1", "Hello", None).unwrap();
5253        cache.tag("article").set("a:2", "World", None).unwrap();
5254        cache.set("untagged", "data", None).unwrap();
5255
5256        cache.tag("article").clear().unwrap();
5257
5258        assert!(cache.get::<String>("a:1").unwrap().is_none());
5259        assert!(cache.get::<String>("a:2").unwrap().is_none());
5260        // 非标签缓存保留
5261        assert_eq!(
5262            cache.get::<String>("untagged").unwrap(),
5263            Some("data".to_string())
5264        );
5265    }
5266
5267    #[test]
5268    fn test_r5_php_tag_redis_with_prefix() {
5269        // R5: Redis 带前缀的 tag 行为对齐 PHP
5270        let cache = Cache::new();
5271        let config = RedisConfig {
5272            prefix: "myapp:".to_string(),
5273            tag_prefix: "tag:".to_string(),
5274            ..RedisConfig::default()
5275        };
5276        let driver = RedisCacheDriver::new(config);
5277        cache.register_store("redis", Box::new(driver));
5278
5279        cache.tag("user").set("u1", "Alice", None).unwrap();
5280
5281        // 验证 tag_items 返回已前缀化的 key
5282        let mgr = cache.manager.read();
5283        let driver = mgr.default_store().unwrap();
5284        let items = driver.tag_items("user").unwrap();
5285        assert_eq!(items, vec!["myapp:u1"]);
5286
5287        // clear 正确删除
5288        drop(mgr);
5289        cache.tag("user").clear().unwrap();
5290        assert!(cache.get::<String>("u1").unwrap().is_none());
5291    }
5292
5293    #[test]
5294    fn test_r5_php_tag_different_tags_isolation() {
5295        // R5: 不同标签之间互不影响
5296        let cache = Cache::new();
5297        cache.register_default(MemoryCacheDriver::new());
5298
5299        cache.tag("user").set("u1", "Alice", None).unwrap();
5300        cache.tag("article").set("a1", "Hello", None).unwrap();
5301
5302        // 清除 user 不影响 article
5303        cache.tag("user").clear().unwrap();
5304
5305        assert!(cache.get::<String>("u1").unwrap().is_none());
5306        assert_eq!(
5307            cache.get::<String>("a1").unwrap(),
5308            Some("Hello".to_string())
5309        );
5310    }
5311
5312    #[test]
5313    fn test_r5_php_tag_set_with_ttl() {
5314        // R5: TagSet::set 支持 TTL
5315        let cache = Cache::new();
5316        cache.register_default(MemoryCacheDriver::new());
5317
5318        cache
5319            .tag("user")
5320            .set("u1", "Alice", Some(Duration::from_millis(50)))
5321            .unwrap();
5322
5323        assert_eq!(
5324            cache.get::<String>("u1").unwrap(),
5325            Some("Alice".to_string())
5326        );
5327
5328        std::thread::sleep(Duration::from_millis(60));
5329        assert!(cache.get::<String>("u1").unwrap().is_none());
5330    }
5331
5332    // ========================================================================
5333    // 测试组 54: delete_many 批量删除(对齐 PHP deleteMultiple)
5334    // ========================================================================
5335
5336    #[test]
5337    fn test_delete_many_multiple_keys() {
5338        // 批量删除多个 key
5339        let cache = Cache::new();
5340        cache.register_default(MemoryCacheDriver::new());
5341        cache.set("k1", "v1", None).unwrap();
5342        cache.set("k2", "v2", None).unwrap();
5343        cache.set("k3", "v3", None).unwrap();
5344
5345        cache.delete_many(&["k1", "k2", "k3"]).unwrap();
5346
5347        assert!(cache.get::<String>("k1").unwrap().is_none());
5348        assert!(cache.get::<String>("k2").unwrap().is_none());
5349        assert!(cache.get::<String>("k3").unwrap().is_none());
5350    }
5351
5352    #[test]
5353    fn test_delete_many_nonexistent_keys_ok() {
5354        // 删除不存在的 key 不失败(修正 PHP File::delete bug)
5355        let cache = Cache::new();
5356        cache.register_default(MemoryCacheDriver::new());
5357        cache.set("exists", "v", None).unwrap();
5358
5359        // 不存在的 key + 存在的 key 混合
5360        let result = cache.delete_many(&["exists", "nonexistent"]);
5361        assert!(result.is_ok());
5362    }
5363
5364    #[test]
5365    fn test_delete_many_empty_slice() {
5366        // 空切片返回 Ok
5367        let cache = Cache::new();
5368        cache.register_default(MemoryCacheDriver::new());
5369        let result = cache.delete_many(&[]);
5370        assert!(result.is_ok());
5371    }
5372
5373    #[test]
5374    fn test_delete_many_partial_delete_before_failure() {
5375        // delete_many 逐个删除,部分成功后失败(对齐 PHP 语义)
5376        // 注:MemoryCacheDriver 不会失败,这里验证空切片+有值切片行为一致性
5377        let cache = Cache::new();
5378        cache.register_default(MemoryCacheDriver::new());
5379        cache.set("a", "1", None).unwrap();
5380        cache.set("b", "2", None).unwrap();
5381
5382        cache.delete_many(&["a", "b"]).unwrap();
5383        assert!(cache.get::<String>("a").unwrap().is_none());
5384        assert!(cache.get::<String>("b").unwrap().is_none());
5385    }
5386
5387    // ========================================================================
5388    // 测试组 55: invalidate_after_write 写后失效
5389    // ========================================================================
5390
5391    #[test]
5392    fn test_invalidate_after_write_basic() {
5393        // 写后失效基本语义:delete 后下次 get 返回 None
5394        let cache = Cache::new();
5395        cache.register_default(MemoryCacheDriver::new());
5396        cache.set("user:1", "Alice", None).unwrap();
5397        assert_eq!(
5398            cache.get::<String>("user:1").unwrap(),
5399            Some("Alice".to_string())
5400        );
5401
5402        // 写操作后失效缓存
5403        cache.invalidate_after_write(&["user:1"]).unwrap();
5404        assert!(cache.get::<String>("user:1").unwrap().is_none());
5405    }
5406
5407    #[test]
5408    fn test_invalidate_after_write_multiple_keys() {
5409        // 多 key 失效(对齐业务场景 4:一次写操作失效多类缓存)
5410        let cache = Cache::new();
5411        cache.register_default(MemoryCacheDriver::new());
5412        cache.set("sdp_category_tree", "t1", None).unwrap();
5413        cache.set("sdp_category_select", "s1", None).unwrap();
5414        cache.set("sdp_category_child", "c1", None).unwrap();
5415
5416        cache
5417            .invalidate_after_write(&[
5418                "sdp_category_tree",
5419                "sdp_category_select",
5420                "sdp_category_child",
5421            ])
5422            .unwrap();
5423
5424        assert!(cache.get::<String>("sdp_category_tree").unwrap().is_none());
5425        assert!(cache
5426            .get::<String>("sdp_category_select")
5427            .unwrap()
5428            .is_none());
5429        assert!(cache.get::<String>("sdp_category_child").unwrap().is_none());
5430    }
5431
5432    #[test]
5433    fn test_invalidate_after_write_fire_and_forget() {
5434        // fire and forget 模式(对齐 PHP 业务代码不检查返回值)
5435        let cache = Cache::new();
5436        cache.register_default(MemoryCacheDriver::new());
5437        cache.set("clerk:1", "data", None).unwrap();
5438
5439        // 用 let _ = 忽略返回值(对齐 PHP fire and forget)
5440        let _ = cache.invalidate_after_write(&["clerk:1"]);
5441        assert!(cache.get::<String>("clerk:1").unwrap().is_none());
5442    }
5443
5444    // ========================================================================
5445    // 测试组 56: refresh 先删后读强制刷新
5446    // ========================================================================
5447
5448    #[test]
5449    fn test_refresh_force_update() {
5450        // 先删后读强制刷新:delete → fetcher → set
5451        let cache = Cache::new();
5452        cache.register_default(MemoryCacheDriver::new());
5453        cache.set("store:1", "old_data", None).unwrap();
5454
5455        let result: String = cache
5456            .refresh("store:1", None, || Ok("new_data".to_string()))
5457            .unwrap();
5458
5459        assert_eq!(result, "new_data");
5460        assert_eq!(
5461            cache.get::<String>("store:1").unwrap(),
5462            Some("new_data".to_string())
5463        );
5464    }
5465
5466    #[test]
5467    fn test_refresh_fetcher_error_no_write() {
5468        // fetcher 失败时不写入缓存(错误传播)
5469        let cache = Cache::new();
5470        cache.register_default(MemoryCacheDriver::new());
5471        cache.set("key", "original", None).unwrap();
5472
5473        // fetcher 返回错误
5474        let result: Result<String, CacheError> = cache.refresh("key", None, || {
5475            Err(CacheError::SerializationError("fetch failed".to_string()))
5476        });
5477
5478        assert!(result.is_err());
5479        // delete 已执行,缓存被清空
5480        assert!(cache.get::<String>("key").unwrap().is_none());
5481    }
5482
5483    #[test]
5484    fn test_refresh_ttl_propagation() {
5485        // TTL 透传到 set
5486        let cache = Cache::new();
5487        cache.register_default(MemoryCacheDriver::new());
5488
5489        let _result: String = cache
5490            .refresh("ttl_key", Some(Duration::from_millis(50)), || {
5491                Ok("value".to_string())
5492            })
5493            .unwrap();
5494
5495        // 立即可读
5496        assert_eq!(
5497            cache.get::<String>("ttl_key").unwrap(),
5498            Some("value".to_string())
5499        );
5500
5501        // 等待过期
5502        std::thread::sleep(Duration::from_millis(60));
5503        assert!(cache.get::<String>("ttl_key").unwrap().is_none());
5504    }
5505
5506    #[test]
5507    fn test_refresh_returns_fetcher_value() {
5508        // refresh 返回 fetcher 的值(不是缓存中的旧值)
5509        // 注:用 String 类型避免 PHP unserialize numeric → string bug 影响
5510        let cache = Cache::new();
5511        cache.register_default(MemoryCacheDriver::new());
5512        cache.set("counter", "old_value", None).unwrap();
5513
5514        let result: String = cache
5515            .refresh("counter", None, || Ok("new_value".to_string()))
5516            .unwrap();
5517        assert_eq!(result, "new_value");
5518        assert_eq!(
5519            cache.get::<String>("counter").unwrap(),
5520            Some("new_value".to_string())
5521        );
5522    }
5523
5524    // ========================================================================
5525    // 测试组 57: R5 PHP 行为对齐(缓存失效策略)
5526    // ========================================================================
5527
5528    #[test]
5529    fn test_r5_php_delete_multiple_semantics() {
5530        // R5: 对齐 PHP Driver::deleteMultiple 逐个删除语义
5531        // PHP: foreach ($keys as $key) { $result = $this->delete($key); if (false === $result) return false; }
5532        let cache = Cache::new();
5533        cache.register_default(MemoryCacheDriver::new());
5534        cache.set("a", "1", None).unwrap();
5535        cache.set("b", "2", None).unwrap();
5536        cache.set("c", "3", None).unwrap();
5537
5538        // 对齐 PHP deleteMultiple(['a', 'b', 'c'])
5539        let result = cache.delete_many(&["a", "b", "c"]);
5540        assert!(result.is_ok()); // PHP 返回 true
5541
5542        // 所有 key 已删除
5543        assert!(cache.get::<String>("a").unwrap().is_none());
5544        assert!(cache.get::<String>("b").unwrap().is_none());
5545        assert!(cache.get::<String>("c").unwrap().is_none());
5546    }
5547
5548    #[test]
5549    fn test_r5_php_invalidate_after_write_pattern() {
5550        // R5: 对齐 PHP 业务场景 1(事务内写后失效)
5551        // PHP: if($this->save($data)){ Cache::delete('foodCashierClerkAll_' . $data['cashier_id']); $this->commit(); }
5552        let cache = Cache::new();
5553        cache.register_default(MemoryCacheDriver::new());
5554
5555        // 模拟业务:先写入缓存数据
5556        cache
5557            .set("foodCashierClerkAll_1", vec!["clerk1"], None)
5558            .unwrap();
5559
5560        // 模拟写操作(如数据库 save)后失效缓存
5561        let write_success = true;
5562        if write_success {
5563            cache
5564                .invalidate_after_write(&["foodCashierClerkAll_1"])
5565                .unwrap();
5566        }
5567
5568        // 缓存已失效,下次 get 返回 None(触发回源)
5569        assert!(cache
5570            .get::<Vec<String>>("foodCashierClerkAll_1")
5571            .unwrap()
5572            .is_none());
5573    }
5574
5575    #[test]
5576    fn test_r5_php_refresh_pattern() {
5577        // R5: 对齐 PHP 业务场景 2(先删后读强制刷新)
5578        // PHP: Cache::delete($cacheKey); $info = Cache::get($cacheKey); if(!$info){ $info = 回源; Cache::set(...); }
5579        let cache = Cache::new();
5580        cache.register_default(MemoryCacheDriver::new());
5581
5582        // 初始缓存数据
5583        cache
5584            .set("wmall_store_info_1", "old_store_data", None)
5585            .unwrap();
5586
5587        // 强制刷新(对齐 PHP info() 方法)
5588        let result: String = cache
5589            .refresh("wmall_store_info_1", None, || {
5590                // 模拟回源查询
5591                Ok("fresh_store_data".to_string())
5592            })
5593            .unwrap();
5594
5595        assert_eq!(result, "fresh_store_data");
5596        assert_eq!(
5597            cache.get::<String>("wmall_store_info_1").unwrap(),
5598            Some("fresh_store_data".to_string())
5599        );
5600    }
5601
5602    // ========================================================================
5603    // 测试组 58: fetch_singleflight 单飞模式(防止缓存击穿)
5604    // ========================================================================
5605
5606    #[test]
5607    fn test_fetch_singleflight_cache_hit() {
5608        // 缓存命中时不调用 fetcher
5609        let cache = Cache::new();
5610        cache.register_default(MemoryCacheDriver::new());
5611        cache.set("hot", "cached_value", None).unwrap();
5612
5613        let called = Arc::new(Mutex::new(false));
5614        let called_clone = called.clone();
5615        let result: String = cache
5616            .fetch_singleflight("hot", None, || {
5617                *called_clone.lock() = true;
5618                Ok("fetcher_value".to_string())
5619            })
5620            .unwrap();
5621
5622        assert_eq!(result, "cached_value");
5623        assert!(!*called.lock(), "fetcher 不应被调用(缓存命中)");
5624    }
5625
5626    #[test]
5627    fn test_fetch_singleflight_cache_miss_invokes_fetcher() {
5628        // 缓存未命中时调用 fetcher 并写入缓存
5629        let cache = Cache::new();
5630        cache.register_default(MemoryCacheDriver::new());
5631
5632        let result: String = cache
5633            .fetch_singleflight("miss_key", None, || Ok("fetched".to_string()))
5634            .unwrap();
5635
5636        assert_eq!(result, "fetched");
5637        assert_eq!(
5638            cache.get::<String>("miss_key").unwrap(),
5639            Some("fetched".to_string())
5640        );
5641    }
5642
5643    #[test]
5644    fn test_fetch_singleflight_concurrent_only_one_fetcher_call() {
5645        // 并发场景:同一 key 多线程请求,fetcher 只调用一次
5646        let cache = Arc::new(Cache::new());
5647        cache.register_default(MemoryCacheDriver::new());
5648
5649        let fetcher_call_count = Arc::new(Mutex::new(0u32));
5650        let barrier = Arc::new(Barrier::new(4));
5651        let results = Arc::new(Mutex::new(Vec::<String>::new()));
5652
5653        let mut handles = Vec::new();
5654        for _ in 0..4 {
5655            let cache_clone = Arc::clone(&cache);
5656            let count_clone = Arc::clone(&fetcher_call_count);
5657            let barrier_clone = Arc::clone(&barrier);
5658            let results_clone = Arc::clone(&results);
5659
5660            handles.push(std::thread::spawn(move || {
5661                // 所有线程同步开始,确保并发
5662                barrier_clone.wait();
5663
5664                let value: String = cache_clone
5665                    .fetch_singleflight("concurrent_key", None, || {
5666                        // 模拟慢回源
5667                        std::thread::sleep(Duration::from_millis(50));
5668                        let mut count = count_clone.lock();
5669                        *count += 1;
5670                        Ok(format!("fetched_{}", *count))
5671                    })
5672                    .unwrap();
5673
5674                results_clone.lock().push(value);
5675            }));
5676        }
5677
5678        for handle in handles {
5679            handle.join().unwrap();
5680        }
5681
5682        // fetcher 应该只被调用一次(singleflight 互斥)
5683        assert_eq!(
5684            *fetcher_call_count.lock(),
5685            1,
5686            "fetcher 应只调用一次(singleflight)"
5687        );
5688
5689        // 所有线程应该拿到相同的值
5690        let results = results.lock();
5691        assert_eq!(results.len(), 4);
5692        for value in results.iter() {
5693            assert_eq!(value, "fetched_1");
5694        }
5695    }
5696
5697    #[test]
5698    fn test_fetch_singleflight_fetcher_error_propagates() {
5699        // fetcher 失败时错误传播,不写入缓存
5700        let cache = Cache::new();
5701        cache.register_default(MemoryCacheDriver::new());
5702
5703        let result: Result<String, CacheError> = cache.fetch_singleflight("err_key", None, || {
5704            Err(CacheError::SerializationError("fetcher failed".to_string()))
5705        });
5706
5707        assert!(result.is_err());
5708        assert!(cache.get::<String>("err_key").unwrap().is_none());
5709    }
5710
5711    // ========================================================================
5712    // 测试组 59: set_with_jitter 随机抖动 TTL(防止缓存雪崩)
5713    // ========================================================================
5714
5715    #[test]
5716    fn test_set_with_jitter_basic() {
5717        // 基本功能:写入缓存且可读
5718        let cache = Cache::new();
5719        cache.register_default(MemoryCacheDriver::new());
5720
5721        cache
5722            .set_with_jitter(
5723                "jitter_key",
5724                "value",
5725                Some(Duration::from_secs(60)),
5726                Duration::from_secs(10),
5727            )
5728            .unwrap();
5729
5730        assert_eq!(
5731            cache.get::<String>("jitter_key").unwrap(),
5732            Some("value".to_string())
5733        );
5734    }
5735
5736    #[test]
5737    fn test_set_with_jitter_zero_jitter_equivalent_to_set() {
5738        // jitter = 0 时等价于 set
5739        let cache = Cache::new();
5740        cache.register_default(MemoryCacheDriver::new());
5741
5742        cache
5743            .set_with_jitter(
5744                "no_jitter",
5745                "value",
5746                Some(Duration::from_secs(60)),
5747                Duration::ZERO,
5748            )
5749            .unwrap();
5750
5751        assert_eq!(
5752            cache.get::<String>("no_jitter").unwrap(),
5753            Some("value".to_string())
5754        );
5755    }
5756
5757    #[test]
5758    fn test_set_with_jitter_none_ttl_no_jitter() {
5759        // ttl = None 时等价于永久缓存,jitter 被忽略
5760        let cache = Cache::new();
5761        cache.register_default(MemoryCacheDriver::new());
5762
5763        cache
5764            .set_with_jitter("permanent", "value", None, Duration::from_secs(10))
5765            .unwrap();
5766
5767        assert_eq!(
5768            cache.get::<String>("permanent").unwrap(),
5769            Some("value".to_string())
5770        );
5771    }
5772
5773    #[test]
5774    fn test_set_with_jitter_ttl_in_expected_range() {
5775        // TTL 在 [ttl, ttl + jitter] 范围内(通过过期时间验证)
5776        let cache = Cache::new();
5777        cache.register_default(MemoryCacheDriver::new());
5778
5779        let base_ttl = Duration::from_millis(50);
5780        let jitter = Duration::from_millis(100);
5781
5782        cache
5783            .set_with_jitter("range_key", "value", Some(base_ttl), jitter)
5784            .unwrap();
5785
5786        // 立即可读
5787        assert!(cache.get::<String>("range_key").unwrap().is_some());
5788
5789        // 等待 base_ttl + jitter + 缓冲后应已过期
5790        std::thread::sleep(base_ttl + jitter + Duration::from_millis(20));
5791        assert!(
5792            cache.get::<String>("range_key").unwrap().is_none(),
5793            "TTL 应在 [{:?}, {:?}] 范围内,已过期",
5794            base_ttl,
5795            base_ttl + jitter
5796        );
5797    }
5798
5799    // ========================================================================
5800    // 测试组 60: fetch_with_protection 组合防护(singleflight + jitter)
5801    // ========================================================================
5802
5803    #[test]
5804    fn test_fetch_with_protection_cache_hit() {
5805        // 缓存命中时不调用 fetcher
5806        let cache = Cache::new();
5807        cache.register_default(MemoryCacheDriver::new());
5808        cache.set("protected", "cached", None).unwrap();
5809
5810        let called = Arc::new(Mutex::new(false));
5811        let called_clone = called.clone();
5812        let result: String = cache
5813            .fetch_with_protection(
5814                "protected",
5815                Some(Duration::from_secs(60)),
5816                Duration::from_secs(10),
5817                || {
5818                    *called_clone.lock() = true;
5819                    Ok("fetched".to_string())
5820                },
5821            )
5822            .unwrap();
5823
5824        assert_eq!(result, "cached");
5825        assert!(!*called.lock());
5826    }
5827
5828    #[test]
5829    fn test_fetch_with_protection_cache_miss_invokes_fetcher() {
5830        // 缓存未命中时调用 fetcher 并写入缓存
5831        let cache = Cache::new();
5832        cache.register_default(MemoryCacheDriver::new());
5833
5834        let result: String = cache
5835            .fetch_with_protection(
5836                "miss_protected",
5837                Some(Duration::from_secs(60)),
5838                Duration::from_secs(10),
5839                || Ok("fetched_protected".to_string()),
5840            )
5841            .unwrap();
5842
5843        assert_eq!(result, "fetched_protected");
5844        assert_eq!(
5845            cache.get::<String>("miss_protected").unwrap(),
5846            Some("fetched_protected".to_string())
5847        );
5848    }
5849
5850    #[test]
5851    fn test_fetch_with_protection_concurrent_single_flight() {
5852        // 并发场景:组合防护下 fetcher 只调用一次
5853        let cache = Arc::new(Cache::new());
5854        cache.register_default(MemoryCacheDriver::new());
5855
5856        let fetcher_call_count = Arc::new(Mutex::new(0u32));
5857        let barrier = Arc::new(Barrier::new(4));
5858        let results = Arc::new(Mutex::new(Vec::<String>::new()));
5859
5860        let mut handles = Vec::new();
5861        for _ in 0..4 {
5862            let cache_clone = Arc::clone(&cache);
5863            let count_clone = Arc::clone(&fetcher_call_count);
5864            let barrier_clone = Arc::clone(&barrier);
5865            let results_clone = Arc::clone(&results);
5866
5867            handles.push(std::thread::spawn(move || {
5868                barrier_clone.wait();
5869
5870                let value: String = cache_clone
5871                    .fetch_with_protection(
5872                        "concurrent_protected",
5873                        Some(Duration::from_secs(60)),
5874                        Duration::from_secs(10),
5875                        || {
5876                            std::thread::sleep(Duration::from_millis(50));
5877                            let mut count = count_clone.lock();
5878                            *count += 1;
5879                            Ok(format!("value_{}", *count))
5880                        },
5881                    )
5882                    .unwrap();
5883
5884                results_clone.lock().push(value);
5885            }));
5886        }
5887
5888        for handle in handles {
5889            handle.join().unwrap();
5890        }
5891
5892        assert_eq!(*fetcher_call_count.lock(), 1, "fetcher 应只调用一次");
5893
5894        let results = results.lock();
5895        assert_eq!(results.len(), 4);
5896        for value in results.iter() {
5897            assert_eq!(value, "value_1");
5898        }
5899    }
5900
5901    #[test]
5902    fn test_fetch_with_protection_fetcher_error_propagates() {
5903        // fetcher 失败时错误传播,不写入缓存
5904        let cache = Cache::new();
5905        cache.register_default(MemoryCacheDriver::new());
5906
5907        let result: Result<String, CacheError> = cache.fetch_with_protection(
5908            "err_protected",
5909            Some(Duration::from_secs(60)),
5910            Duration::from_secs(10),
5911            || Err(CacheError::SerializationError("failed".to_string())),
5912        );
5913
5914        assert!(result.is_err());
5915        assert!(cache.get::<String>("err_protected").unwrap().is_none());
5916    }
5917
5918    // ========================================================================
5919    // 测试组 61: R5 PHP 行为对比(缓存防护)
5920    // ========================================================================
5921
5922    #[test]
5923    fn test_r5_php_remember_lock_vs_rust_singleflight() {
5924        // R5: 对比 PHP remember 的"锁雏形"与 Rust singleflight 的正确实现
5925        // PHP remember 用 $this->set($name.'_lock', true) 非原子加锁(缺陷)
5926        // Rust singleflight 用 parking_lot::Mutex::lock() 原子互斥(正确)
5927        let cache = Arc::new(Cache::new());
5928        cache.register_default(MemoryCacheDriver::new());
5929
5930        let call_count = Arc::new(Mutex::new(0u32));
5931        let barrier = Arc::new(Barrier::new(3));
5932        let results = Arc::new(Mutex::new(Vec::<String>::new()));
5933
5934        let mut handles = Vec::new();
5935        for _ in 0..3 {
5936            let cache_clone = Arc::clone(&cache);
5937            let count_clone = Arc::clone(&call_count);
5938            let barrier_clone = Arc::clone(&barrier);
5939            let results_clone = Arc::clone(&results);
5940
5941            handles.push(std::thread::spawn(move || {
5942                barrier_clone.wait();
5943
5944                let value: String = cache_clone
5945                    .fetch_singleflight("r5_compare_key", None, || {
5946                        std::thread::sleep(Duration::from_millis(30));
5947                        let mut count = count_clone.lock();
5948                        *count += 1;
5949                        Ok(format!("v_{}", *count))
5950                    })
5951                    .unwrap();
5952
5953                results_clone.lock().push(value);
5954            }));
5955        }
5956
5957        for handle in handles {
5958            handle.join().unwrap();
5959        }
5960
5961        // Rust singleflight:fetcher 只调用一次(对齐"正确互斥"语义)
5962        assert_eq!(
5963            *call_count.lock(),
5964            1,
5965            "Rust singleflight fetcher 应只调用一次"
5966        );
5967
5968        // 所有线程拿到相同值
5969        let results = results.lock();
5970        assert_eq!(results.len(), 3);
5971        for value in results.iter() {
5972            assert_eq!(value, "v_1");
5973        }
5974    }
5975
5976    #[test]
5977    fn test_r5_php_no_jitter_vs_rust_jitter() {
5978        // R5: 对比 PHP 无 TTL 抖动与 Rust 有 TTL 抖动
5979        // PHP getExpireTime 不做 TTL 抖动(缺陷,会雪崩)
5980        // Rust set_with_jitter 在 [ttl, ttl + jitter] 范围内随机(正确,防雪崩)
5981        let cache = Cache::new();
5982        cache.register_default(MemoryCacheDriver::new());
5983
5984        // 多次设置相同 TTL + jitter,验证实际 TTL 不同(随机性)
5985        let mut ttl_samples = Vec::new();
5986        for i in 0..10 {
5987            let key = format!("jitter_sample_{}", i);
5988            cache
5989                .set_with_jitter(
5990                    &key,
5991                    "value",
5992                    Some(Duration::from_secs(60)),
5993                    Duration::from_secs(10),
5994                )
5995                .unwrap();
5996
5997            // 通过 MemoryCacheDriver 内部 TTL 验证随机性
5998            // 注:这里只验证缓存写入成功,实际 TTL 随机性通过统计方法验证
5999            let _ = cache.get::<String>(&key).unwrap();
6000            ttl_samples.push(key);
6001        }
6002
6003        // 验证所有 key 都写入成功
6004        for key in &ttl_samples {
6005            assert_eq!(
6006                cache.get::<String>(key).unwrap(),
6007                Some("value".to_string()),
6008                "所有带抖动 TTL 的 key 都应写入成功"
6009            );
6010        }
6011    }
6012
6013    #[test]
6014    fn test_r5_php_remember_no_double_check_vs_rust_double_check() {
6015        // R5: 对比 PHP remember 无 double-check 与 Rust singleflight 有 double-check
6016        // PHP remember 获取锁后直接回源,不再次检查缓存(缺陷)
6017        // Rust singleflight 获取锁后 double-check 缓存(优化,其他线程可能已回源完成)
6018        let cache = Cache::new();
6019        cache.register_default(MemoryCacheDriver::new());
6020
6021        // 先写入缓存
6022        cache.set("double_check_key", "pre_cached", None).unwrap();
6023
6024        // 调用 fetch_singleflight,应直接命中缓存(不调用 fetcher)
6025        let called = Arc::new(Mutex::new(false));
6026        let called_clone = called.clone();
6027        let result: String = cache
6028            .fetch_singleflight("double_check_key", None, || {
6029                *called_clone.lock() = true;
6030                Ok("fetched".to_string())
6031            })
6032            .unwrap();
6033
6034        // 应返回预缓存的值,fetcher 不被调用
6035        assert_eq!(result, "pre_cached");
6036        assert!(
6037            !*called.lock(),
6038            "double-check 应命中预缓存,fetcher 不被调用"
6039        );
6040    }
6041
6042    // ========================================================================
6043    // 混沌工程测试(P3-CHAOS-01 ~ P3-CHAOS-03)
6044    // ========================================================================
6045    // 注意:fetch_singleflight 是同步 API,Cache 不实现 Clone。
6046    // 并发测试统一使用 std::thread + Arc 模式(与 test_fetch_singleflight_concurrent_only_one_fetcher_call 一致)。
6047
6048    /// P3-CHAOS-01:缓存雪崩防护 — singleflight 合并并发请求
6049    ///
6050    /// 模拟 50 个并发请求同时请求同一个未缓存的 key。
6051    /// 预期:singleflight 将 50 个请求合并为 1 次实际回源,
6052    /// 其余 49 个请求等待同一结果,不触发缓存击穿。
6053    #[test]
6054    fn test_cache_thundering_herd_singleflight_collapses() {
6055        let cache = Arc::new(Cache::new());
6056        cache.register_default(MemoryCacheDriver::new());
6057
6058        let call_count = Arc::new(Mutex::new(0u32));
6059        let num_tasks = 50;
6060        let barrier = Arc::new(Barrier::new(num_tasks));
6061        let mut handles = Vec::new();
6062
6063        for _ in 0..num_tasks {
6064            let cache = Arc::clone(&cache);
6065            let cc = Arc::clone(&call_count);
6066            let barrier = Arc::clone(&barrier);
6067            handles.push(std::thread::spawn(move || {
6068                barrier.wait(); // 所有线程同步开始,确保真正并发
6069                let result: String = cache
6070                    .fetch_singleflight("herd_key", None, || {
6071                        // 模拟慢回源
6072                        *cc.lock() += 1;
6073                        std::thread::sleep(Duration::from_millis(10));
6074                        Ok("single_source".to_string())
6075                    })
6076                    .unwrap();
6077                result
6078            }));
6079        }
6080
6081        let results: Vec<_> = handles.into_iter().map(|h| h.join().unwrap()).collect();
6082
6083        // 所有线程应返回相同结果
6084        for r in &results {
6085            assert_eq!(r, "single_source");
6086        }
6087
6088        // 实际回源次数应为 1(singleflight 合并)
6089        let calls = *call_count.lock();
6090        assert_eq!(
6091            calls, 1,
6092            "P3-CHAOS-01: 50 并发请求应合并为 1 次实际回源,实际 {} 次",
6093            calls
6094        );
6095    }
6096
6097    /// P3-CHAOS-02:缓存降级 — 慢回源超时场景
6098    ///
6099    /// fetch_singleflight 是同步阻塞 API。验证:
6100    /// 1. 慢回源在阈值时间内不会完成(调用方需自行用 spawn_blocking + timeout 包裹)
6101    /// 2. 慢回源最终完成后结果正确传播(使用 mpsc + recv_timeout 模拟降级判定)
6102    #[test]
6103    fn test_cache_slow_backend_timeout_degradation() {
6104        let cache = Cache::new();
6105        cache.register_default(MemoryCacheDriver::new());
6106
6107        let (tx, rx) = std::sync::mpsc::channel::<String>();
6108
6109        // 在独立线程中执行慢回源
6110        let handle = std::thread::spawn(move || {
6111            let result: String = cache
6112                .fetch_singleflight("slow_key", None, || {
6113                    std::thread::sleep(Duration::from_millis(500));
6114                    Ok("slow_value".to_string())
6115                })
6116                .unwrap();
6117            let _ = tx.send(result);
6118        });
6119
6120        // 200ms 内不应收到结果(慢回源需要 500ms)
6121        let early = rx.recv_timeout(Duration::from_millis(200));
6122        assert!(
6123            early.is_err(),
6124            "P3-CHAOS-02: 慢回源(500ms)在 200ms 内不应完成,调用方应已触发超时降级"
6125        );
6126
6127        // 等待慢线程完成并验证最终结果正确传播
6128        handle.join().unwrap();
6129        let final_val = rx.recv_timeout(Duration::from_secs(2)).unwrap();
6130        assert_eq!(
6131            final_val, "slow_value",
6132            "P3-CHAOS-02: 慢回源完成后结果应正确传播"
6133        );
6134    }
6135
6136    /// P3-CHAOS-03:TTL 过期 + 并发写入压力测试
6137    ///
6138    /// 在高并发写入 + 短 TTL 的场景下验证:
6139    /// - 过期 key 被正确清理
6140    /// - 并发写入不导致数据损坏
6141    /// - TTL 过期后缓存可恢复正常使用
6142    #[test]
6143    fn test_cache_ttl_eviction_under_concurrent_load() {
6144        use std::time::Duration;
6145
6146        let cache = Arc::new(Cache::new());
6147        cache.register_default(MemoryCacheDriver::new());
6148
6149        let num_writers = 16;
6150        let writes_per_writer = 100;
6151        let ttl = Duration::from_millis(50);
6152        let barrier = Arc::new(Barrier::new(num_writers));
6153
6154        let mut handles = Vec::new();
6155
6156        // 高并发写入(所有写入使用相同 key 集合,制造竞争)
6157        for w in 0..num_writers {
6158            let cache = Arc::clone(&cache);
6159            let barrier = Arc::clone(&barrier);
6160            handles.push(std::thread::spawn(move || {
6161                barrier.wait(); // 同步开始
6162                for i in 0..writes_per_writer {
6163                    let key = format!("ttl_key_{}", i % 20); // 20 个 key 循环写入
6164                    let val = format!("writer{}_val{}", w, i);
6165                    let _ = cache.set(&key, &val, Some(ttl));
6166                }
6167            }));
6168        }
6169
6170        for h in handles {
6171            h.join().unwrap();
6172        }
6173
6174        // 等待 TTL 过期
6175        std::thread::sleep(ttl * 3);
6176
6177        // 所有 key 应已过期(返回 None)
6178        for i in 0..20 {
6179            let key = format!("ttl_key_{}", i);
6180            let val: Option<String> = cache.get(&key).unwrap();
6181            assert!(
6182                val.is_none(),
6183                "P3-CHAOS-03: key={} 应在 TTL 过期后为 None,实际 {:?}",
6184                key,
6185                val
6186            );
6187        }
6188
6189        // 写入新值验证缓存仍可正常使用
6190        cache.set("post_eviction_key", "fresh", None).unwrap();
6191        let val: Option<String> = cache.get("post_eviction_key").unwrap();
6192        assert_eq!(val, Some("fresh".to_string()));
6193    }
6194}