1use std::collections::HashMap;
194use std::sync::{Arc, OnceLock};
195use std::time::{Duration, Instant};
196
197use parking_lot::{Mutex, RwLock};
198use serde::de::DeserializeOwned;
199use serde::Serialize;
200
201use sz_orm_core::Cache as InnerCache;
202use sz_orm_core::CacheError;
203use sz_orm_core::MemoryCache;
204
205static GLOBAL_CACHE: OnceLock<Cache> = OnceLock::new();
215
216pub fn default_cache() -> &'static Cache {
234 GLOBAL_CACHE.get_or_init(Cache::new)
235}
236
237pub fn init_default_cache(driver: MemoryCacheDriver) {
250 let cache = default_cache();
251 cache.register_default(driver);
252}
253
254#[derive(Debug, Clone, PartialEq)]
269pub enum CacheValue {
270 Number(String),
274 Json(String),
278}
279
280impl CacheValue {
281 pub fn to_bytes(&self) -> Vec<u8> {
285 match self {
286 CacheValue::Number(s) => s.as_bytes().to_vec(),
287 CacheValue::Json(s) => s.as_bytes().to_vec(),
288 }
289 }
290
291 pub fn from_bytes(bytes: &[u8]) -> Result<CacheValue, CacheError> {
297 let s = std::str::from_utf8(bytes)
298 .map_err(|e| CacheError::DeserializationError(e.to_string()))?;
299 if php_is_numeric(s) {
300 Ok(CacheValue::Number(s.to_string()))
301 } else {
302 Ok(CacheValue::Json(s.to_string()))
303 }
304 }
305
306 pub fn is_number(&self) -> bool {
308 matches!(self, CacheValue::Number(_))
309 }
310}
311
312pub fn php_is_numeric(s: &str) -> bool {
343 if s.is_empty() {
344 return false;
345 }
346 if s.parse::<i64>().is_ok() {
348 return true;
349 }
350 if s.parse::<f64>().is_ok() {
352 return true;
353 }
354 false
357}
358
359pub fn php_serialize<T: Serialize>(value: &T) -> Result<CacheValue, CacheError> {
373 let json =
376 serde_json::to_string(value).map_err(|e| CacheError::SerializationError(e.to_string()))?;
377
378 if php_is_numeric(&json) {
382 Ok(CacheValue::Number(json))
383 } else {
384 Ok(CacheValue::Json(json))
385 }
386}
387
388pub fn php_unserialize<T: DeserializeOwned>(value: &CacheValue) -> Result<Option<T>, CacheError> {
402 match value {
403 CacheValue::Number(s) => {
404 serde_json::from_str::<T>(&format!("\"{}\"", s))
407 .map(Some)
408 .map_err(|e| CacheError::DeserializationError(e.to_string()))
409 }
410 CacheValue::Json(s) => serde_json::from_str::<T>(s)
411 .map(Some)
412 .map_err(|e| CacheError::DeserializationError(e.to_string())),
413 }
414}
415
416pub trait CacheDriver: Send + Sync {
437 fn get_raw(&self, key: &str) -> Result<Option<Vec<u8>>, CacheError>;
439
440 fn set_raw(&self, key: &str, value: Vec<u8>, ttl: Option<Duration>) -> Result<(), CacheError>;
442
443 fn delete(&self, key: &str) -> Result<(), CacheError>;
445
446 fn has(&self, key: &str) -> Result<bool, CacheError>;
448
449 fn inc(&self, key: &str, step: i64) -> Result<i64, CacheError> {
460 let current = match self.get_raw(key)? {
461 Some(bytes) => {
462 let s = std::str::from_utf8(&bytes)
463 .map_err(|e| CacheError::DeserializationError(e.to_string()))?;
464 s.parse::<i64>().map_err(|e| {
465 CacheError::DeserializationError(format!("inc: parse {} failed: {}", s, e))
466 })?
467 }
468 None => 0,
469 };
470 let new_value = current + step;
471 self.set_raw(key, new_value.to_string().into_bytes(), None)?;
472 Ok(new_value)
473 }
474
475 fn dec(&self, key: &str, step: i64) -> Result<i64, CacheError> {
479 self.inc(key, -step)
480 }
481
482 fn clear(&self) -> Result<(), CacheError>;
484
485 fn get_cache_key(&self, name: &str) -> String {
499 name.to_string()
500 }
501
502 fn get_tag_key(&self, tag: &str) -> String {
511 format!("tag:{}", compute_md5(tag))
512 }
513
514 fn tag_append(&self, tag_key: &str, cache_key: &str) -> Result<(), CacheError> {
551 let storage_key = self.get_cache_key(tag_key);
552 let mut items: Vec<String> = match self.get_raw(&storage_key)? {
554 Some(bytes) => serde_json::from_slice(&bytes)
555 .map_err(|e| CacheError::DeserializationError(format!("tag_append: {}", e)))?,
556 None => Vec::new(),
557 };
558 items.push(cache_key.to_string());
560 while items.len() > 1000 {
562 items.remove(0);
563 }
564 let mut seen = HashSet::new();
566 items.retain(|item| seen.insert(item.clone()));
567 let serialized = serde_json::to_vec(&items)
569 .map_err(|e| CacheError::SerializationError(e.to_string()))?;
570 self.set_raw(&storage_key, serialized, None)
571 }
572
573 fn tag_items(&self, tag: &str) -> Result<Vec<String>, CacheError> {
592 let tag_key = self.get_tag_key(tag);
593 let storage_key = self.get_cache_key(&tag_key);
594 match self.get_raw(&storage_key)? {
595 Some(bytes) => {
596 let items: Vec<String> = serde_json::from_slice(&bytes)
597 .map_err(|e| CacheError::DeserializationError(format!("tag_items: {}", e)))?;
598 Ok(items)
599 }
600 None => Ok(Vec::new()),
601 }
602 }
603
604 fn tag_clear(&self, keys: &[String]) -> Result<(), CacheError> {
622 for key in keys {
623 let _ = self.delete(key);
624 }
625 Ok(())
626 }
627}
628
629pub struct MemoryCacheDriver {
648 inner: MemoryCache,
649}
650
651impl MemoryCacheDriver {
652 pub fn new() -> Self {
654 Self {
655 inner: MemoryCache::new(),
656 }
657 }
658
659 pub fn with_default_ttl(ttl: Duration) -> Self {
661 Self {
662 inner: MemoryCache::with_ttl(ttl),
663 }
664 }
665}
666
667impl Default for MemoryCacheDriver {
668 fn default() -> Self {
669 Self::new()
670 }
671}
672
673impl CacheDriver for MemoryCacheDriver {
674 fn get_raw(&self, key: &str) -> Result<Option<Vec<u8>>, CacheError> {
675 InnerCache::get(&self.inner, key)
676 }
677
678 fn set_raw(&self, key: &str, value: Vec<u8>, ttl: Option<Duration>) -> Result<(), CacheError> {
679 InnerCache::set(&self.inner, key, value, ttl)
680 }
681
682 fn delete(&self, key: &str) -> Result<(), CacheError> {
683 InnerCache::delete(&self.inner, key)
684 }
685
686 fn has(&self, key: &str) -> Result<bool, CacheError> {
687 InnerCache::exists(&self.inner, key)
688 }
689
690 fn clear(&self) -> Result<(), CacheError> {
691 InnerCache::clear(&self.inner)
692 }
693}
694
695pub struct CacheManager {
715 default: String,
717 stores: HashMap<String, Box<dyn CacheDriver>>,
719}
720
721impl CacheManager {
722 pub fn new() -> Self {
724 Self {
725 default: String::new(),
726 stores: HashMap::new(),
727 }
728 }
729
730 pub fn register_store(&mut self, name: impl Into<String>, driver: Box<dyn CacheDriver>) {
739 let name = name.into();
740 if self.default.is_empty() {
741 self.default = name.clone();
742 }
743 self.stores.insert(name, driver);
744 }
745
746 pub fn set_default(&mut self, name: impl Into<String>) -> Result<(), CacheError> {
750 let name = name.into();
751 if !self.stores.contains_key(&name) {
752 return Err(CacheError::NotFound(format!(
753 "cache store '{}' not registered",
754 name
755 )));
756 }
757 self.default = name;
758 Ok(())
759 }
760
761 pub fn store(&self, name: &str) -> Result<&dyn CacheDriver, CacheError> {
765 self.stores
766 .get(name)
767 .map(|d| d.as_ref())
768 .ok_or_else(|| CacheError::NotFound(format!("cache store '{}' not found", name)))
769 }
770
771 pub fn default_store(&self) -> Result<&dyn CacheDriver, CacheError> {
775 if self.default.is_empty() {
776 return Err(CacheError::NotFound(
777 "no default cache store registered".to_string(),
778 ));
779 }
780 self.store(&self.default)
781 }
782}
783
784impl Default for CacheManager {
785 fn default() -> Self {
786 Self::new()
787 }
788}
789
790pub struct Cache {
819 manager: RwLock<CacheManager>,
820 remember_lock_poll_interval: Duration,
822 remember_lock_timeout: Duration,
823 inflight: Mutex<HashMap<String, Arc<Mutex<()>>>>,
826}
827
828impl Cache {
829 pub fn new() -> Self {
831 Self {
832 manager: RwLock::new(CacheManager::new()),
833 remember_lock_poll_interval: Duration::from_millis(200),
834 remember_lock_timeout: Duration::from_secs(5),
835 inflight: Mutex::new(HashMap::new()),
836 }
837 }
838
839 pub fn register_default(&self, driver: MemoryCacheDriver) {
843 let mut mgr = self.manager.write();
844 mgr.register_store("default", Box::new(driver));
845 }
846
847 pub fn register_store(&self, name: impl Into<String>, driver: Box<dyn CacheDriver>) {
849 let mut mgr = self.manager.write();
850 mgr.register_store(name, driver);
851 }
852
853 pub fn set_default_store(&self, name: impl Into<String>) -> Result<(), CacheError> {
855 let mut mgr = self.manager.write();
856 mgr.set_default(name)
857 }
858
859 #[tracing::instrument(skip(self, value))]
885 pub fn set<T: Serialize>(
886 &self,
887 key: &str,
888 value: T,
889 ttl: Option<Duration>,
890 ) -> Result<(), CacheError> {
891 let cache_value = php_serialize(&value)?;
892 let bytes = cache_value.to_bytes();
893 let mgr = self.manager.read();
894 let driver = mgr.default_store()?;
895 driver.set_raw(key, bytes, ttl)
896 }
897
898 #[tracing::instrument(skip(self))]
934 pub fn get<T: DeserializeOwned>(&self, key: &str) -> Result<Option<T>, CacheError> {
935 let mgr = self.manager.read();
936 let driver = mgr.default_store()?;
937 match driver.get_raw(key)? {
938 None => Ok(None),
939 Some(bytes) => {
940 let cache_value = CacheValue::from_bytes(&bytes)?;
941 php_unserialize(&cache_value)
942 }
943 }
944 }
945
946 pub fn get_or<T: DeserializeOwned>(&self, key: &str, default: T) -> Result<T, CacheError> {
948 match self.get::<T>(key)? {
949 Some(v) => Ok(v),
950 None => Ok(default),
951 }
952 }
953
954 fn get_weak<T: DeserializeOwned>(&self, key: &str) -> Result<Option<T>, CacheError> {
972 match self.get::<T>(key) {
973 Ok(v) => Ok(v),
974 Err(CacheError::DeserializationError(_)) => {
975 match self.get::<String>(key) {
978 Ok(Some(s)) => serde_json::from_str::<T>(&s)
979 .map(Some)
980 .map_err(|e| CacheError::DeserializationError(e.to_string())),
981 Ok(None) => Ok(None),
982 Err(e) => Err(e),
983 }
984 }
985 Err(e) => Err(e),
986 }
987 }
988
989 #[tracing::instrument(skip(self))]
991 pub fn delete(&self, key: &str) -> Result<(), CacheError> {
992 let mgr = self.manager.read();
993 let driver = mgr.default_store()?;
994 driver.delete(key)
995 }
996
997 pub fn has(&self, key: &str) -> Result<bool, CacheError> {
1012 let mgr = self.manager.read();
1013 let driver = mgr.default_store()?;
1014 driver.has(key)
1015 }
1016
1017 pub fn inc(&self, key: &str, step: i64) -> Result<i64, CacheError> {
1027 let mgr = self.manager.read();
1028 let driver = mgr.default_store()?;
1029 driver.inc(key, step)
1030 }
1031
1032 pub fn dec(&self, key: &str, step: i64) -> Result<i64, CacheError> {
1034 let mgr = self.manager.read();
1035 let driver = mgr.default_store()?;
1036 driver.dec(key, step)
1037 }
1038
1039 pub fn increment(&self, key: &str) -> Result<i64, CacheError> {
1041 self.inc(key, 1)
1042 }
1043
1044 pub fn decrement(&self, key: &str) -> Result<i64, CacheError> {
1046 self.dec(key, 1)
1047 }
1048
1049 pub fn pull<T: DeserializeOwned>(&self, key: &str) -> Result<Option<T>, CacheError> {
1062 let value = self.get::<T>(key)?;
1063 if value.is_some() {
1064 self.delete(key)?;
1065 }
1066 Ok(value)
1067 }
1068
1069 pub fn push<T: Serialize + DeserializeOwned + PartialEq + Clone>(
1098 &self,
1099 key: &str,
1100 value: T,
1101 ttl: Option<Duration>,
1102 ) -> Result<(), CacheError> {
1103 let mut data: Vec<T> = match self.get::<Vec<T>>(key) {
1106 Ok(Some(v)) => v,
1107 Ok(None) => Vec::new(),
1108 Err(_) => Vec::new(),
1109 };
1110 data.push(value);
1111
1112 while data.len() > 1000 {
1114 data.remove(0);
1115 }
1116
1117 let mut seen = std::collections::HashSet::new();
1119 data.retain(|item| seen.insert(item.hashable_string()));
1120
1121 self.set(key, data, ttl)
1122 }
1123
1124 #[tracing::instrument(skip(self, callback))]
1152 pub fn remember<T, F>(
1153 &self,
1154 key: &str,
1155 ttl: Option<Duration>,
1156 callback: F,
1157 ) -> Result<T, CacheError>
1158 where
1159 T: Serialize + DeserializeOwned,
1160 F: FnOnce() -> T,
1161 {
1162 if let Some(cached) = self.get_weak::<T>(key)? {
1164 return Ok(cached);
1165 }
1166
1167 let lock_key = format!("{}_lock", key);
1169
1170 if self.has(&lock_key)? {
1172 let start = Instant::now();
1174 while self.has(&lock_key)? {
1175 if start.elapsed() >= self.remember_lock_timeout {
1176 return Ok(callback());
1178 }
1179 std::thread::sleep(self.remember_lock_poll_interval);
1180 }
1181
1182 if let Some(cached) = self.get_weak::<T>(key)? {
1184 return Ok(cached);
1185 }
1186 }
1187
1188 self.set(&lock_key, 1i64, None)?;
1190
1191 let result = callback();
1193 let _ = self.set(key, &result, ttl);
1194
1195 let _ = self.delete(&lock_key);
1197
1198 Ok(result)
1199 }
1200
1201 pub async fn remember_async<T, F, Fut>(
1232 &self,
1233 key: &str,
1234 ttl: Option<Duration>,
1235 callback: F,
1236 ) -> Result<T, CacheError>
1237 where
1238 T: Serialize + DeserializeOwned + Clone,
1239 F: FnOnce() -> Fut,
1240 Fut: std::future::Future<Output = T>,
1241 {
1242 if let Some(cached) = self.get_weak::<T>(key)? {
1244 return Ok(cached);
1245 }
1246
1247 let lock_key = format!("{}_lock", key);
1249
1250 if self.has(&lock_key)? {
1252 let start = Instant::now();
1254 while self.has(&lock_key)? {
1255 if start.elapsed() >= self.remember_lock_timeout {
1256 let result = callback().await;
1258 let _ = self.set(key, &result, ttl);
1259 return Ok(result);
1260 }
1261 tokio::time::sleep(self.remember_lock_poll_interval).await;
1262 }
1263
1264 if let Some(cached) = self.get_weak::<T>(key)? {
1266 return Ok(cached);
1267 }
1268 }
1269
1270 self.set(&lock_key, 1i64, None)?;
1272
1273 let result = callback().await;
1275 let _ = self.set(key, &result, ttl);
1276
1277 let _ = self.delete(&lock_key);
1279
1280 Ok(result)
1281 }
1282
1283 #[tracing::instrument(skip(self))]
1285 pub fn clear(&self) -> Result<(), CacheError> {
1286 let mgr = self.manager.read();
1287 let driver = mgr.default_store()?;
1288 driver.clear()
1289 }
1290
1291 pub fn delete_many(&self, keys: &[&str]) -> Result<(), CacheError> {
1336 let mgr = self.manager.read();
1337 let driver = mgr.default_store()?;
1338 for key in keys {
1339 driver.delete(key)?;
1341 }
1342 Ok(())
1343 }
1344
1345 pub fn invalidate_after_write(&self, keys: &[&str]) -> Result<(), CacheError> {
1380 self.delete_many(keys)
1381 }
1382
1383 pub fn refresh<T, F>(
1420 &self,
1421 key: &str,
1422 ttl: Option<Duration>,
1423 fetcher: F,
1424 ) -> Result<T, CacheError>
1425 where
1426 T: Serialize + DeserializeOwned,
1427 F: FnOnce() -> Result<T, CacheError>,
1428 {
1429 self.delete(key)?;
1431
1432 let value = fetcher()?;
1434
1435 self.set(key, &value, ttl)?;
1437
1438 Ok(value)
1439 }
1440
1441 #[tracing::instrument(skip(self, fetcher))]
1477 pub fn fetch_singleflight<T, F>(
1478 &self,
1479 key: &str,
1480 ttl: Option<Duration>,
1481 fetcher: F,
1482 ) -> Result<T, CacheError>
1483 where
1484 T: Serialize + DeserializeOwned,
1485 F: FnOnce() -> Result<T, CacheError>,
1486 {
1487 if let Some(cached) = self.get::<T>(key)? {
1489 return Ok(cached);
1490 }
1491
1492 let mutex = {
1495 let mut inflight = self.inflight.lock();
1496 inflight
1497 .entry(key.to_string())
1498 .or_insert_with(|| Arc::new(Mutex::new(())))
1499 .clone()
1500 };
1501
1502 let _guard = mutex.lock();
1504
1505 if let Some(cached) = self.get::<T>(key)? {
1507 return Ok(cached);
1508 }
1509
1510 let value = fetcher()?;
1512 self.set(key, &value, ttl)?;
1513
1514 Ok(value)
1515 }
1516
1517 pub fn set_with_jitter<T>(
1536 &self,
1537 key: &str,
1538 value: &T,
1539 ttl: Option<Duration>,
1540 jitter: Duration,
1541 ) -> Result<(), CacheError>
1542 where
1543 T: Serialize + ?Sized,
1544 {
1545 let actual_ttl = match ttl {
1546 Some(t) if !jitter.is_zero() => {
1547 use rand::Rng;
1549 let jitter_nanos = jitter.as_nanos() as u64;
1550 let random_jitter =
1551 Duration::from_nanos(rand::thread_rng().gen_range(0..jitter_nanos));
1552 Some(t + random_jitter)
1553 }
1554 Some(t) => Some(t),
1555 None => None,
1556 };
1557 self.set(key, value, actual_ttl)
1558 }
1559
1560 #[tracing::instrument(skip(self, fetcher))]
1576 pub fn fetch_with_protection<T, F>(
1577 &self,
1578 key: &str,
1579 ttl: Option<Duration>,
1580 jitter: Duration,
1581 fetcher: F,
1582 ) -> Result<T, CacheError>
1583 where
1584 T: Serialize + DeserializeOwned,
1585 F: FnOnce() -> Result<T, CacheError>,
1586 {
1587 if let Some(cached) = self.get::<T>(key)? {
1589 return Ok(cached);
1590 }
1591
1592 let mutex = {
1594 let mut inflight = self.inflight.lock();
1595 inflight
1596 .entry(key.to_string())
1597 .or_insert_with(|| Arc::new(Mutex::new(())))
1598 .clone()
1599 };
1600
1601 let _guard = mutex.lock();
1603
1604 if let Some(cached) = self.get::<T>(key)? {
1606 return Ok(cached);
1607 }
1608
1609 let value = fetcher()?;
1611 self.set_with_jitter(key, &value, ttl, jitter)?;
1612
1613 Ok(value)
1614 }
1615
1616 pub fn with_store<R, F>(&self, name: &str, f: F) -> Result<R, CacheError>
1632 where
1633 F: FnOnce(&dyn CacheDriver) -> Result<R, CacheError>,
1634 {
1635 let mgr = self.manager.read();
1636 let driver = mgr.store(name)?;
1637 f(driver)
1638 }
1639
1640 pub fn tag(&self, name: &str) -> TagSet<'_> {
1672 TagSet {
1673 tags: vec![name.to_string()],
1674 cache: self,
1675 }
1676 }
1677
1678 pub fn tag_many(&self, names: &[&str]) -> TagSet<'_> {
1690 TagSet {
1691 tags: names.iter().map(|s| s.to_string()).collect(),
1692 cache: self,
1693 }
1694 }
1695}
1696
1697impl Default for Cache {
1698 fn default() -> Self {
1699 Self::new()
1700 }
1701}
1702
1703trait CloneHashable: Clone {
1712 fn hashable_string(&self) -> String;
1713}
1714
1715impl<T> CloneHashable for T
1716where
1717 T: Serialize + Clone,
1718{
1719 fn hashable_string(&self) -> String {
1720 serde_json::to_string(self).unwrap_or_default()
1721 }
1722}
1723
1724use md5::{Digest, Md5};
1748use std::collections::HashSet;
1749
1750#[derive(Debug, Clone)]
1769pub struct RedisConfig {
1770 pub host: String,
1772 pub port: u16,
1774 pub password: String,
1776 pub select: u32,
1778 pub timeout: Duration,
1780 pub expire: Option<Duration>,
1782 pub persistent: bool,
1784 pub prefix: String,
1786 pub tag_prefix: String,
1788}
1789
1790impl Default for RedisConfig {
1791 fn default() -> Self {
1792 Self {
1793 host: "127.0.0.1".to_string(),
1794 port: 6379,
1795 password: String::new(),
1796 select: 0,
1797 timeout: Duration::ZERO,
1798 expire: None,
1799 persistent: false,
1800 prefix: String::new(),
1801 tag_prefix: "tag:".to_string(),
1802 }
1803 }
1804}
1805
1806impl RedisConfig {
1807 pub fn with_prefix(prefix: impl Into<String>) -> Self {
1809 Self {
1810 prefix: prefix.into(),
1811 ..Default::default()
1812 }
1813 }
1814
1815 pub fn with_expire(expire: Duration) -> Self {
1817 Self {
1818 expire: Some(expire),
1819 ..Default::default()
1820 }
1821 }
1822}
1823
1824pub trait RedisBackend: Send + Sync {
1849 fn get(&self, key: &str) -> Result<Option<Vec<u8>>, CacheError>;
1851 fn set(&self, key: &str, value: Vec<u8>) -> Result<(), CacheError>;
1853 fn set_ex(&self, key: &str, value: Vec<u8>, ttl: Duration) -> Result<(), CacheError>;
1855 fn del(&self, key: &str) -> Result<i64, CacheError>;
1857 fn del_many(&self, keys: &[&str]) -> Result<i64, CacheError>;
1859 fn exists(&self, key: &str) -> Result<bool, CacheError>;
1861 fn incr_by(&self, key: &str, step: i64) -> Result<i64, CacheError>;
1863 fn decr_by(&self, key: &str, step: i64) -> Result<i64, CacheError>;
1865 fn flush_db(&self) -> Result<(), CacheError>;
1867 fn sadd(&self, key: &str, member: &str) -> Result<i64, CacheError>;
1869 fn smembers(&self, key: &str) -> Result<Vec<String>, CacheError>;
1871}
1872
1873pub struct MockRedisBackend {
1884 kv: parking_lot::RwLock<MockRedisKv>,
1886 sets: parking_lot::RwLock<MockRedisSets>,
1888}
1889
1890type MockRedisKv = HashMap<String, (Vec<u8>, Option<Instant>)>;
1892
1893type MockRedisSets = HashMap<String, HashSet<String>>;
1895
1896impl Default for MockRedisBackend {
1897 fn default() -> Self {
1898 Self::new()
1899 }
1900}
1901
1902impl MockRedisBackend {
1903 pub fn new() -> Self {
1905 Self {
1906 kv: parking_lot::RwLock::new(HashMap::new()),
1907 sets: parking_lot::RwLock::new(HashMap::new()),
1908 }
1909 }
1910
1911 fn is_expired(kv: &MockRedisKv, key: &str) -> bool {
1913 if let Some((_, Some(expires_at))) = kv.get(key) {
1914 return *expires_at <= Instant::now();
1915 }
1916 false
1917 }
1918}
1919
1920impl RedisBackend for MockRedisBackend {
1921 fn get(&self, key: &str) -> Result<Option<Vec<u8>>, CacheError> {
1922 let kv = self.kv.read();
1923 if Self::is_expired(&kv, key) {
1924 return Ok(None);
1925 }
1926 Ok(kv.get(key).map(|(v, _)| v.clone()))
1927 }
1928
1929 fn set(&self, key: &str, value: Vec<u8>) -> Result<(), CacheError> {
1930 let mut kv = self.kv.write();
1931 kv.insert(key.to_string(), (value, None));
1932 Ok(())
1933 }
1934
1935 fn set_ex(&self, key: &str, value: Vec<u8>, ttl: Duration) -> Result<(), CacheError> {
1936 let mut kv = self.kv.write();
1937 let expires_at = Some(Instant::now() + ttl);
1938 kv.insert(key.to_string(), (value, expires_at));
1939 Ok(())
1940 }
1941
1942 fn del(&self, key: &str) -> Result<i64, CacheError> {
1943 let mut kv = self.kv.write();
1944 let removed = kv.remove(key).is_some() as i64;
1945 let mut sets = self.sets.write();
1947 if sets.remove(key).is_some() && removed == 0 {
1948 return Ok(1);
1949 }
1950 Ok(removed)
1951 }
1952
1953 fn del_many(&self, keys: &[&str]) -> Result<i64, CacheError> {
1954 let mut count = 0i64;
1955 for key in keys {
1956 count += self.del(key)?;
1957 }
1958 Ok(count)
1959 }
1960
1961 fn exists(&self, key: &str) -> Result<bool, CacheError> {
1962 let kv = self.kv.read();
1963 if Self::is_expired(&kv, key) {
1964 return Ok(false);
1965 }
1966 if kv.contains_key(key) {
1967 return Ok(true);
1968 }
1969 let sets = self.sets.read();
1970 Ok(sets.contains_key(key))
1971 }
1972
1973 fn incr_by(&self, key: &str, step: i64) -> Result<i64, CacheError> {
1974 let mut kv = self.kv.write();
1975 if Self::is_expired(&kv, key) {
1977 kv.remove(key);
1978 }
1979 let current = match kv.get(key) {
1980 Some((bytes, _)) => {
1981 let s = std::str::from_utf8(bytes)
1982 .map_err(|e| CacheError::DeserializationError(e.to_string()))?;
1983 s.parse::<i64>().map_err(|e| {
1984 CacheError::Internal(format!("INCRBY failed: '{}' is not an integer: {}", s, e))
1985 })?
1986 }
1987 None => 0, };
1989 let new_value = current + step;
1990 kv.insert(key.to_string(), (new_value.to_string().into_bytes(), None));
1991 Ok(new_value)
1992 }
1993
1994 fn decr_by(&self, key: &str, step: i64) -> Result<i64, CacheError> {
1995 self.incr_by(key, -step)
1997 }
1998
1999 fn flush_db(&self) -> Result<(), CacheError> {
2000 let mut kv = self.kv.write();
2001 kv.clear();
2002 let mut sets = self.sets.write();
2003 sets.clear();
2004 Ok(())
2005 }
2006
2007 fn sadd(&self, key: &str, member: &str) -> Result<i64, CacheError> {
2008 let mut sets = self.sets.write();
2009 let set = sets.entry(key.to_string()).or_default();
2010 let added = set.insert(member.to_string()) as i64;
2011 Ok(added)
2012 }
2013
2014 fn smembers(&self, key: &str) -> Result<Vec<String>, CacheError> {
2015 let sets = self.sets.read();
2016 Ok(sets
2017 .get(key)
2018 .map(|s| s.iter().cloned().collect())
2019 .unwrap_or_default())
2020 }
2021}
2022
2023pub struct RedisCacheDriver {
2075 backend: Box<dyn RedisBackend>,
2076 config: RedisConfig,
2077}
2078
2079impl RedisCacheDriver {
2080 pub fn new(config: RedisConfig) -> Self {
2084 Self::with_backend(config, Box::new(MockRedisBackend::new()))
2085 }
2086
2087 pub fn with_backend(config: RedisConfig, backend: Box<dyn RedisBackend>) -> Self {
2091 Self { backend, config }
2092 }
2093
2094 pub fn config(&self) -> &RedisConfig {
2096 &self.config
2097 }
2098
2099 pub fn backend(&self) -> &dyn RedisBackend {
2101 self.backend.as_ref()
2102 }
2103
2104 pub fn append(&self, name: &str, value: &str) -> Result<(), CacheError> {
2118 let key = self.get_cache_key(name);
2119 self.backend.sadd(&key, value)?;
2120 Ok(())
2121 }
2122
2123 pub fn get_tag_items(&self, tag: &str) -> Result<Vec<String>, CacheError> {
2135 let name = self.get_tag_key(tag);
2136 let key = self.get_cache_key(&name);
2137 self.backend.smembers(&key)
2138 }
2139
2140 pub fn clear_tag(&self, keys: &[&str]) -> Result<(), CacheError> {
2150 self.backend.del_many(keys)?;
2151 Ok(())
2152 }
2153
2154 pub fn tag_key(&self, tag: &str) -> String {
2156 self.get_tag_key(tag)
2157 }
2158
2159 pub fn cache_key(&self, name: &str) -> String {
2161 self.get_cache_key(name)
2162 }
2163}
2164
2165impl CacheDriver for RedisCacheDriver {
2166 fn get_raw(&self, key: &str) -> Result<Option<Vec<u8>>, CacheError> {
2167 let cache_key = self.get_cache_key(key);
2168 self.backend.get(&cache_key)
2169 }
2170
2171 fn set_raw(&self, key: &str, value: Vec<u8>, ttl: Option<Duration>) -> Result<(), CacheError> {
2172 let cache_key = self.get_cache_key(key);
2173 let effective_ttl = ttl.or(self.config.expire);
2175 match effective_ttl {
2177 Some(t) if t > Duration::ZERO => self.backend.set_ex(&cache_key, value, t),
2178 _ => self.backend.set(&cache_key, value),
2179 }
2180 }
2181
2182 fn delete(&self, key: &str) -> Result<(), CacheError> {
2183 let cache_key = self.get_cache_key(key);
2184 self.backend.del(&cache_key)?;
2186 Ok(())
2187 }
2188
2189 fn has(&self, key: &str) -> Result<bool, CacheError> {
2190 let cache_key = self.get_cache_key(key);
2191 self.backend.exists(&cache_key)
2193 }
2194
2195 fn inc(&self, key: &str, step: i64) -> Result<i64, CacheError> {
2211 let cache_key = self.get_cache_key(key);
2212 self.backend.incr_by(&cache_key, step)
2213 }
2214
2215 fn dec(&self, key: &str, step: i64) -> Result<i64, CacheError> {
2217 let cache_key = self.get_cache_key(key);
2218 self.backend.decr_by(&cache_key, step)
2219 }
2220
2221 fn clear(&self) -> Result<(), CacheError> {
2222 self.backend.flush_db()
2224 }
2225
2226 fn get_cache_key(&self, name: &str) -> String {
2234 format!("{}{}", self.config.prefix, name)
2235 }
2236
2237 fn get_tag_key(&self, tag: &str) -> String {
2241 let md5_hex = compute_md5(tag);
2242 format!("{}{}", self.config.tag_prefix, md5_hex)
2243 }
2244
2245 fn tag_append(&self, tag_key: &str, cache_key: &str) -> Result<(), CacheError> {
2259 let key = self.get_cache_key(tag_key);
2260 self.backend.sadd(&key, cache_key)?;
2261 Ok(())
2262 }
2263
2264 fn tag_items(&self, tag: &str) -> Result<Vec<String>, CacheError> {
2276 let name = self.get_tag_key(tag);
2277 let key = self.get_cache_key(&name);
2278 self.backend.smembers(&key)
2279 }
2280
2281 fn tag_clear(&self, keys: &[String]) -> Result<(), CacheError> {
2294 let key_refs: Vec<&str> = keys.iter().map(|s| s.as_str()).collect();
2295 self.backend.del_many(&key_refs)?;
2296 Ok(())
2297 }
2298}
2299
2300fn compute_md5(s: &str) -> String {
2304 let mut hasher = Md5::new();
2305 hasher.update(s.as_bytes());
2306 let result = hasher.finalize();
2307 hex::encode(result)
2308}
2309
2310pub struct MultiLevelCacheDriver {
2340 inner: sz_orm_core::MultiLevelCache,
2341}
2342
2343impl Default for MultiLevelCacheDriver {
2344 fn default() -> Self {
2345 Self::new()
2346 }
2347}
2348
2349impl MultiLevelCacheDriver {
2350 pub fn new() -> Self {
2352 Self {
2353 inner: sz_orm_core::MultiLevelCache::new(),
2354 }
2355 }
2356
2357 pub fn add_level(mut self, cache: Box<dyn InnerCache>) -> Self {
2361 self.inner = self.inner.add_cache(cache);
2362 self
2363 }
2364
2365 pub fn inner(&self) -> &sz_orm_core::MultiLevelCache {
2367 &self.inner
2368 }
2369}
2370
2371impl CacheDriver for MultiLevelCacheDriver {
2372 fn get_raw(&self, key: &str) -> Result<Option<Vec<u8>>, CacheError> {
2373 self.inner.get(key)
2374 }
2375
2376 fn set_raw(&self, key: &str, value: Vec<u8>, ttl: Option<Duration>) -> Result<(), CacheError> {
2377 self.inner.set(key, value, ttl)
2378 }
2379
2380 fn delete(&self, key: &str) -> Result<(), CacheError> {
2381 self.inner.delete(key)
2382 }
2383
2384 fn has(&self, key: &str) -> Result<bool, CacheError> {
2385 self.inner.exists(key)
2386 }
2387
2388 fn inc(&self, key: &str, step: i64) -> Result<i64, CacheError> {
2389 let current = match self.inner.get(key)? {
2392 Some(bytes) => String::from_utf8(bytes)
2393 .map_err(|e| CacheError::DeserializationError(e.to_string()))?
2394 .parse::<i64>()
2395 .unwrap_or(0),
2396 None => 0,
2397 };
2398 let new_value = current + step;
2399 let new_bytes = new_value.to_string().into_bytes();
2400 let ttl = self.inner.ttl(key).ok().flatten();
2402 self.inner.set(key, new_bytes, ttl)?;
2403 Ok(new_value)
2404 }
2405
2406 fn dec(&self, key: &str, step: i64) -> Result<i64, CacheError> {
2407 let current = match self.inner.get(key)? {
2409 Some(bytes) => String::from_utf8(bytes)
2410 .map_err(|e| CacheError::DeserializationError(e.to_string()))?
2411 .parse::<i64>()
2412 .unwrap_or(0),
2413 None => 0,
2414 };
2415 let new_value = current - step;
2416 let new_bytes = new_value.to_string().into_bytes();
2417 let ttl = self.inner.ttl(key).ok().flatten();
2418 self.inner.set(key, new_bytes, ttl)?;
2419 Ok(new_value)
2420 }
2421
2422 fn clear(&self) -> Result<(), CacheError> {
2423 self.inner.clear()
2424 }
2425}
2426
2427pub struct TagSet<'a> {
2482 tags: Vec<String>,
2484 cache: &'a Cache,
2486}
2487
2488impl<'a> TagSet<'a> {
2489 pub fn set<T: Serialize>(
2501 &self,
2502 key: &str,
2503 value: T,
2504 ttl: Option<Duration>,
2505 ) -> Result<(), CacheError> {
2506 self.cache.set(key, value, ttl)?;
2508 self.append(key)
2510 }
2511
2512 pub fn append(&self, key: &str) -> Result<(), CacheError> {
2528 let mgr = self.cache.manager.read();
2529 let driver = mgr.default_store()?;
2530 let cache_key = driver.get_cache_key(key);
2532 for tag in &self.tags {
2534 let tag_key = driver.get_tag_key(tag);
2536 driver.tag_append(&tag_key, &cache_key)?;
2538 }
2539 Ok(())
2540 }
2541
2542 pub fn clear(&self) -> Result<(), CacheError> {
2561 let mgr = self.cache.manager.read();
2562 let driver = mgr.default_store()?;
2563 for tag in &self.tags {
2564 let items = driver.tag_items(tag)?;
2566 driver.tag_clear(&items)?;
2568 let tag_key = driver.get_tag_key(tag);
2570 driver.delete(&tag_key)?;
2572 }
2573 Ok(())
2574 }
2575
2576 pub fn tags(&self) -> &[String] {
2578 &self.tags
2579 }
2580}
2581
2582#[cfg(test)]
2587mod tests {
2588 use super::*;
2589 use serde::Deserialize;
2590 use std::sync::Barrier;
2591
2592 fn make_cache() -> Cache {
2594 let cache = Cache::new();
2595 cache.register_default(MemoryCacheDriver::new());
2596 cache
2597 }
2598
2599 #[test]
2604 fn test_php_is_numeric_integer() {
2605 assert!(php_is_numeric("42"));
2607 assert!(php_is_numeric("-42"));
2608 assert!(php_is_numeric("+42"));
2609 assert!(php_is_numeric("0"));
2610 }
2611
2612 #[test]
2613 fn test_php_is_numeric_float() {
2614 assert!(php_is_numeric("3.14"));
2616 assert!(php_is_numeric("-3.14"));
2617 assert!(php_is_numeric("+3.14"));
2618 assert!(php_is_numeric("0.0"));
2619 }
2620
2621 #[test]
2622 fn test_php_is_numeric_scientific_notation() {
2623 assert!(php_is_numeric("1e10"));
2625 assert!(php_is_numeric("1.5E-3"));
2626 }
2627
2628 #[test]
2629 fn test_php_is_numeric_non_numeric() {
2630 assert!(!php_is_numeric("abc"));
2632 assert!(!php_is_numeric("12abc"));
2633 assert!(!php_is_numeric(""));
2634 assert!(!php_is_numeric("0x1A")); assert!(!php_is_numeric("null"));
2636 assert!(!php_is_numeric("true"));
2637 }
2638
2639 #[test]
2644 fn test_php_serialize_integer_to_number() {
2645 let v = php_serialize(&42i64).unwrap();
2647 assert!(matches!(v, CacheValue::Number(_)));
2648 if let CacheValue::Number(s) = v {
2649 assert_eq!(s, "42");
2650 }
2651 }
2652
2653 #[test]
2654 fn test_php_serialize_float_to_number() {
2655 let v = php_serialize(&2.5f64).unwrap();
2658 assert!(matches!(v, CacheValue::Number(_)));
2659 if let CacheValue::Number(s) = v {
2660 assert_eq!(s, "2.5");
2661 }
2662 }
2663
2664 #[test]
2665 fn test_php_serialize_string_to_json() {
2666 let v = php_serialize(&"Alice".to_string()).unwrap();
2669 assert!(matches!(v, CacheValue::Json(_)));
2670 if let CacheValue::Json(s) = v {
2671 assert_eq!(s, "\"Alice\"");
2672 }
2673 }
2674
2675 #[test]
2676 fn test_php_serialize_numeric_string_to_number() {
2677 let v = php_serialize(&"42".to_string()).unwrap();
2686 assert!(matches!(v, CacheValue::Json(_))); }
2688
2689 #[test]
2690 fn test_php_serialize_array_to_json() {
2691 let v = php_serialize(&vec![1, 2, 3]).unwrap();
2693 assert!(matches!(v, CacheValue::Json(_)));
2694 if let CacheValue::Json(s) = v {
2695 assert_eq!(s, "[1,2,3]");
2696 }
2697 }
2698
2699 #[test]
2700 fn test_php_unserialize_number_returns_string() {
2701 let v = CacheValue::Number("42".to_string());
2704 let result: Option<String> = php_unserialize(&v).unwrap();
2705 assert_eq!(result, Some("42".to_string()));
2706 }
2707
2708 #[test]
2709 fn test_php_unserialize_json_returns_struct() {
2710 let v = CacheValue::Json("\"Alice\"".to_string());
2712 let result: Option<String> = php_unserialize(&v).unwrap();
2713 assert_eq!(result, Some("Alice".to_string()));
2714
2715 let v = CacheValue::Json("[1,2,3]".to_string());
2716 let result: Option<Vec<i64>> = php_unserialize(&v).unwrap();
2717 assert_eq!(result, Some(vec![1, 2, 3]));
2718 }
2719
2720 #[test]
2721 fn test_php_unserialize_number_to_int_via_parse() {
2722 let v = CacheValue::Number("42".to_string());
2725 let s: String = php_unserialize(&v).unwrap().unwrap();
2726 let n: i64 = s.parse().unwrap();
2727 assert_eq!(n, 42);
2728 }
2729
2730 #[test]
2735 fn test_cache_value_number_roundtrip() {
2736 let v = CacheValue::Number("42".to_string());
2737 let bytes = v.to_bytes();
2738 let restored = CacheValue::from_bytes(&bytes).unwrap();
2739 assert_eq!(v, restored);
2740 }
2741
2742 #[test]
2743 fn test_cache_value_json_roundtrip() {
2744 let v = CacheValue::Json("\"Alice\"".to_string());
2745 let bytes = v.to_bytes();
2746 let restored = CacheValue::from_bytes(&bytes).unwrap();
2747 assert_eq!(v, restored);
2748 }
2749
2750 #[test]
2751 fn test_cache_value_array_roundtrip() {
2752 let v = CacheValue::Json("[1,2,3]".to_string());
2753 let bytes = v.to_bytes();
2754 let restored = CacheValue::from_bytes(&bytes).unwrap();
2755 assert_eq!(v, restored);
2756 }
2757
2758 #[test]
2759 fn test_cache_value_from_bytes_numeric_string_becomes_number() {
2760 let bytes = b"42".to_vec();
2762 let v = CacheValue::from_bytes(&bytes).unwrap();
2763 assert!(matches!(v, CacheValue::Number(_)));
2764 }
2765
2766 #[test]
2767 fn test_cache_value_from_bytes_json_string_becomes_json() {
2768 let bytes = b"\"Alice\"".to_vec();
2770 let v = CacheValue::from_bytes(&bytes).unwrap();
2771 assert!(matches!(v, CacheValue::Json(_)));
2772 }
2773
2774 #[test]
2779 fn test_memory_driver_set_get_raw() {
2780 let driver = MemoryCacheDriver::new();
2781 driver.set_raw("key", b"value".to_vec(), None).unwrap();
2782 let val = driver.get_raw("key").unwrap();
2783 assert_eq!(val, Some(b"value".to_vec()));
2784 }
2785
2786 #[test]
2787 fn test_memory_driver_delete() {
2788 let driver = MemoryCacheDriver::new();
2789 driver.set_raw("key", b"value".to_vec(), None).unwrap();
2790 driver.delete("key").unwrap();
2791 let val = driver.get_raw("key").unwrap();
2792 assert_eq!(val, None);
2793 }
2794
2795 #[test]
2796 fn test_memory_driver_has() {
2797 let driver = MemoryCacheDriver::new();
2798 driver.set_raw("key", b"value".to_vec(), None).unwrap();
2799 assert!(driver.has("key").unwrap());
2800 assert!(!driver.has("nonexistent").unwrap());
2801 }
2802
2803 #[test]
2804 fn test_memory_driver_clear() {
2805 let driver = MemoryCacheDriver::new();
2806 driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
2807 driver.set_raw("key2", b"value2".to_vec(), None).unwrap();
2808 driver.clear().unwrap();
2809 assert!(!driver.has("key1").unwrap());
2810 assert!(!driver.has("key2").unwrap());
2811 }
2812
2813 #[test]
2814 fn test_memory_driver_ttl_expiration() {
2815 let driver = MemoryCacheDriver::new();
2816 driver
2817 .set_raw("key", b"value".to_vec(), Some(Duration::from_millis(50)))
2818 .unwrap();
2819 assert!(driver.get_raw("key").unwrap().is_some());
2820 std::thread::sleep(Duration::from_millis(100));
2821 assert!(driver.get_raw("key").unwrap().is_none());
2822 }
2823
2824 #[test]
2825 fn test_memory_driver_inc_default_implementation() {
2826 let driver = MemoryCacheDriver::new();
2828
2829 let v = driver.inc("counter", 5).unwrap();
2831 assert_eq!(v, 5);
2832
2833 let v = driver.inc("counter", 3).unwrap();
2835 assert_eq!(v, 8);
2836 }
2837
2838 #[test]
2839 fn test_memory_driver_dec_default_implementation() {
2840 let driver = MemoryCacheDriver::new();
2841
2842 let v = driver.dec("counter", 3).unwrap();
2844 assert_eq!(v, -3);
2845
2846 let v = driver.dec("counter", 2).unwrap();
2848 assert_eq!(v, -5);
2849 }
2850
2851 #[test]
2856 fn test_cache_manager_register_and_get_default() {
2857 let mut mgr = CacheManager::new();
2858 mgr.register_store("default", Box::new(MemoryCacheDriver::new()));
2859
2860 let driver = mgr.default_store().unwrap();
2861 driver.set_raw("key", b"value".to_vec(), None).unwrap();
2862 assert_eq!(driver.get_raw("key").unwrap(), Some(b"value".to_vec()));
2863 }
2864
2865 #[test]
2866 fn test_cache_manager_multiple_stores_isolation() {
2867 let mut mgr = CacheManager::new();
2868 mgr.register_store("file", Box::new(MemoryCacheDriver::new()));
2869 mgr.register_store("redis", Box::new(MemoryCacheDriver::new()));
2870
2871 let file_driver = mgr.store("file").unwrap();
2872 let redis_driver = mgr.store("redis").unwrap();
2873
2874 file_driver
2875 .set_raw("key", b"file_value".to_vec(), None)
2876 .unwrap();
2877 redis_driver
2878 .set_raw("key", b"redis_value".to_vec(), None)
2879 .unwrap();
2880
2881 assert_eq!(
2883 file_driver.get_raw("key").unwrap(),
2884 Some(b"file_value".to_vec())
2885 );
2886 assert_eq!(
2887 redis_driver.get_raw("key").unwrap(),
2888 Some(b"redis_value".to_vec())
2889 );
2890 }
2891
2892 #[test]
2893 fn test_cache_manager_set_default() {
2894 let mut mgr = CacheManager::new();
2895 mgr.register_store("file", Box::new(MemoryCacheDriver::new()));
2896 mgr.register_store("redis", Box::new(MemoryCacheDriver::new()));
2897
2898 let driver = mgr.default_store().unwrap();
2900 driver.set_raw("file_key", b"file".to_vec(), None).unwrap();
2901 assert_eq!(driver.get_raw("file_key").unwrap(), Some(b"file".to_vec()));
2902
2903 mgr.set_default("redis").unwrap();
2905 let driver = mgr.default_store().unwrap();
2906 driver
2907 .set_raw("redis_key", b"redis".to_vec(), None)
2908 .unwrap();
2909 assert_eq!(
2910 driver.get_raw("redis_key").unwrap(),
2911 Some(b"redis".to_vec())
2912 );
2913 }
2914
2915 #[test]
2916 fn test_cache_manager_default_store_not_registered_error() {
2917 let mgr = CacheManager::new();
2918 let result = mgr.default_store();
2919 assert!(matches!(result, Err(CacheError::NotFound(_))));
2920 }
2921
2922 #[test]
2923 fn test_cache_manager_store_not_found_error() {
2924 let mgr = CacheManager::new();
2925 let result = mgr.store("nonexistent");
2926 assert!(matches!(result, Err(CacheError::NotFound(_))));
2927 }
2928
2929 #[test]
2934 fn test_cache_set_get_string() {
2935 let cache = make_cache();
2936 cache.set("name", "Alice", None).unwrap();
2937 let val: Option<String> = cache.get("name").unwrap();
2938 assert_eq!(val, Some("Alice".to_string()));
2939 }
2940
2941 #[test]
2942 fn test_cache_set_get_int_as_string_php_bug() {
2943 let cache = make_cache();
2946 cache.set("count", 42i64, None).unwrap();
2947
2948 let s: Option<String> = cache.get("count").unwrap();
2951 assert_eq!(s, Some("42".to_string()));
2952
2953 let n: i64 = s.unwrap().parse().unwrap();
2954 assert_eq!(n, 42);
2955 }
2956
2957 #[test]
2958 fn test_cache_set_get_struct() {
2959 #[derive(Serialize, Deserialize, PartialEq, Debug)]
2960 struct User {
2961 name: String,
2962 age: u32,
2963 }
2964
2965 let cache = make_cache();
2966 let user = User {
2967 name: "Alice".to_string(),
2968 age: 30,
2969 };
2970 cache.set("user:1", &user, None).unwrap();
2971
2972 let val: Option<User> = cache.get("user:1").unwrap();
2973 assert_eq!(val, Some(user));
2974 }
2975
2976 #[test]
2977 fn test_cache_set_get_vec() {
2978 let cache = make_cache();
2979 let list = vec![1, 2, 3];
2980 cache.set("list", &list, None).unwrap();
2981
2982 let val: Option<Vec<i64>> = cache.get("list").unwrap();
2983 assert_eq!(val, Some(vec![1, 2, 3]));
2984 }
2985
2986 #[test]
2987 fn test_cache_get_miss_returns_none() {
2988 let cache = make_cache();
2989 let val: Option<String> = cache.get("nonexistent").unwrap();
2990 assert_eq!(val, None);
2991 }
2992
2993 #[test]
2994 fn test_cache_get_or_default_value() {
2995 let cache = make_cache();
2996 let val: String = cache.get_or("nonexistent", "default".to_string()).unwrap();
2997 assert_eq!(val, "default");
2998 }
2999
3000 #[test]
3001 fn test_cache_set_with_ttl_expires() {
3002 let cache = make_cache();
3003 cache
3004 .set("key", "value", Some(Duration::from_millis(50)))
3005 .unwrap();
3006 assert!(cache.get::<String>("key").unwrap().is_some());
3007 std::thread::sleep(Duration::from_millis(100));
3008 assert!(cache.get::<String>("key").unwrap().is_none());
3009 }
3010
3011 #[test]
3016 fn test_cache_delete() {
3017 let cache = make_cache();
3018 cache.set("key", "value", None).unwrap();
3019 assert!(cache.has("key").unwrap());
3020
3021 cache.delete("key").unwrap();
3022 assert!(!cache.has("key").unwrap());
3023
3024 cache.delete("nonexistent").unwrap();
3026 }
3027
3028 #[test]
3029 fn test_cache_has_checks_ttl() {
3030 let cache = make_cache();
3031 cache
3032 .set("key", "value", Some(Duration::from_millis(50)))
3033 .unwrap();
3034 assert!(cache.has("key").unwrap());
3035
3036 std::thread::sleep(Duration::from_millis(100));
3037 assert!(!cache.has("key").unwrap());
3039 }
3040
3041 #[test]
3042 fn test_cache_clear() {
3043 let cache = make_cache();
3044 cache.set("key1", "value1", None).unwrap();
3045 cache.set("key2", "value2", None).unwrap();
3046
3047 cache.clear().unwrap();
3048
3049 assert!(!cache.has("key1").unwrap());
3050 assert!(!cache.has("key2").unwrap());
3051 }
3052
3053 #[test]
3058 fn test_cache_inc_initial_value() {
3059 let cache = make_cache();
3061 let v = cache.inc("counter", 5).unwrap();
3062 assert_eq!(v, 5);
3063
3064 let s: String = cache.get("counter").unwrap().unwrap();
3066 assert_eq!(s, "5");
3067 }
3068
3069 #[test]
3070 fn test_cache_inc_accumulate() {
3071 let cache = make_cache();
3072 cache.inc("counter", 5).unwrap();
3073 cache.inc("counter", 3).unwrap();
3074 let v = cache.inc("counter", 2).unwrap();
3075 assert_eq!(v, 10);
3076 }
3077
3078 #[test]
3079 fn test_cache_dec_initial_value() {
3080 let cache = make_cache();
3082 let v = cache.dec("counter", 3).unwrap();
3083 assert_eq!(v, -3);
3084 }
3085
3086 #[test]
3087 fn test_cache_dec_accumulate() {
3088 let cache = make_cache();
3089 cache.set("counter", 100i64, None).unwrap();
3090 cache.dec("counter", 30).unwrap();
3091 let v = cache.dec("counter", 20).unwrap();
3092 assert_eq!(v, 50);
3093 }
3094
3095 #[test]
3096 fn test_cache_increment_default_step_1() {
3097 let cache = make_cache();
3098 let v = cache.increment("counter").unwrap();
3099 assert_eq!(v, 1);
3100 let v = cache.increment("counter").unwrap();
3101 assert_eq!(v, 2);
3102 }
3103
3104 #[test]
3105 fn test_cache_decrement_default_step_1() {
3106 let cache = make_cache();
3107 let v = cache.decrement("counter").unwrap();
3108 assert_eq!(v, -1);
3109 let v = cache.decrement("counter").unwrap();
3110 assert_eq!(v, -2);
3111 }
3112
3113 #[test]
3118 fn test_cache_pull_existing_key() {
3119 let cache = make_cache();
3121 cache.set("key", "value", None).unwrap();
3122
3123 let val: Option<String> = cache.pull("key").unwrap();
3124 assert_eq!(val, Some("value".to_string()));
3125
3126 assert!(!cache.has("key").unwrap());
3128 }
3129
3130 #[test]
3131 fn test_cache_pull_missing_key_returns_none() {
3132 let cache = make_cache();
3133 let val: Option<String> = cache.pull("nonexistent").unwrap();
3134 assert_eq!(val, None);
3135 }
3136
3137 #[test]
3142 fn test_cache_push_initial_array() {
3143 let cache = make_cache();
3144 cache.push("list", "a".to_string(), None).unwrap();
3145
3146 let val: Option<Vec<String>> = cache.get("list").unwrap();
3147 assert_eq!(val, Some(vec!["a".to_string()]));
3148 }
3149
3150 #[test]
3151 fn test_cache_push_appends() {
3152 let cache = make_cache();
3153 cache.push("list", "a".to_string(), None).unwrap();
3154 cache.push("list", "b".to_string(), None).unwrap();
3155 cache.push("list", "c".to_string(), None).unwrap();
3156
3157 let val: Option<Vec<String>> = cache.get("list").unwrap();
3158 assert_eq!(
3159 val,
3160 Some(vec!["a".to_string(), "b".to_string(), "c".to_string()])
3161 );
3162 }
3163
3164 #[test]
3165 fn test_cache_push_deduplication() {
3166 let cache = make_cache();
3168 cache.push("list", "a".to_string(), None).unwrap();
3169 cache.push("list", "b".to_string(), None).unwrap();
3170 cache.push("list", "a".to_string(), None).unwrap(); cache.push("list", "c".to_string(), None).unwrap();
3172 cache.push("list", "b".to_string(), None).unwrap(); let val: Option<Vec<String>> = cache.get("list").unwrap();
3175 assert_eq!(
3176 val,
3177 Some(vec!["a".to_string(), "b".to_string(), "c".to_string()])
3178 );
3179 }
3180
3181 #[test]
3182 fn test_cache_push_max_1000_fifo() {
3183 let cache = make_cache();
3185
3186 for i in 0..1001i64 {
3188 cache.push("list", i, None).unwrap();
3189 }
3190
3191 let val: Option<Vec<i64>> = cache.get("list").unwrap();
3192 let list = val.unwrap();
3193
3194 assert_eq!(list.len(), 1000);
3196 assert_eq!(list[0], 1);
3198 assert_eq!(list[999], 1000);
3200 }
3201
3202 #[test]
3203 fn test_cache_push_non_array_becomes_array() {
3204 let cache = make_cache();
3206
3207 cache.set("key", "not_an_array".to_string(), None).unwrap();
3209
3210 cache.push("key", "first".to_string(), None).unwrap();
3212
3213 let val: Option<Vec<String>> = cache.get("key").unwrap();
3214 assert_eq!(val, Some(vec!["first".to_string()]));
3215 }
3216
3217 #[test]
3222 fn test_cache_remember_cache_miss() {
3223 let cache = make_cache();
3225 let counter = std::sync::Arc::new(std::sync::atomic::AtomicU32::new(0));
3226 let counter_clone = counter.clone();
3227
3228 let val: i64 = cache
3229 .remember("expensive", None, || {
3230 counter_clone.fetch_add(1, std::sync::atomic::Ordering::SeqCst) as i64 + 100
3231 })
3232 .unwrap();
3233 assert_eq!(val, 100);
3234
3235 let val: i64 = cache
3237 .remember("expensive", None, || {
3238 counter_clone.fetch_add(1, std::sync::atomic::Ordering::SeqCst) as i64 + 200
3239 })
3240 .unwrap();
3241 assert_eq!(val, 100); assert_eq!(counter.load(std::sync::atomic::Ordering::SeqCst), 1);
3245 }
3246
3247 #[test]
3248 fn test_cache_remember_cache_hit_returns_cached() {
3249 let cache = make_cache();
3250 cache.set("predefined", 42i64, None).unwrap();
3251
3252 let val: i64 = cache
3254 .remember("predefined", None, || {
3255 panic!("callback should not be called on cache hit");
3256 })
3257 .unwrap();
3258 assert_eq!(val, 42);
3259 }
3260
3261 #[test]
3262 fn test_cache_remember_writes_with_ttl() {
3263 let cache = make_cache();
3264 cache
3265 .remember("key", Some(Duration::from_millis(50)), || 42i64)
3266 .unwrap();
3267
3268 assert_eq!(cache.get::<String>("key").unwrap(), Some("42".to_string()));
3270
3271 std::thread::sleep(Duration::from_millis(100));
3273 assert!(cache.get::<String>("key").unwrap().is_none());
3274 }
3275
3276 #[test]
3277 fn test_cache_remember_releases_lock_on_success() {
3278 let cache = make_cache();
3280 cache.remember("key", None, || 42i64).unwrap();
3281
3282 assert!(!cache.has("key_lock").unwrap());
3284 }
3285
3286 #[test]
3287 fn test_cache_remember_releases_lock_on_panic() {
3288 let cache = make_cache();
3294 let _ = cache.remember("key", None, || 42i64);
3295 assert!(!cache.has("key_lock").unwrap());
3296 }
3297
3298 #[test]
3299 fn test_cache_remember_lock_has_no_ttl_php_bug() {
3300 let cache = make_cache();
3308 cache.remember("key", None, || 42i64).unwrap();
3309 assert!(!cache.has("key_lock").unwrap());
3310 }
3311
3312 #[tokio::test]
3313 async fn test_cache_remember_async_cache_miss() {
3314 let cache = make_cache();
3316 let counter = std::sync::Arc::new(std::sync::atomic::AtomicU32::new(0));
3317 let counter_clone = counter.clone();
3318
3319 let val: i64 = cache
3320 .remember_async("expensive_async", None, || {
3321 let counter_clone = counter_clone.clone();
3322 async move {
3323 counter_clone.fetch_add(1, std::sync::atomic::Ordering::SeqCst) as i64 + 100
3324 }
3325 })
3326 .await
3327 .unwrap();
3328 assert_eq!(val, 100);
3329
3330 let val: i64 = cache
3332 .remember_async("expensive_async", None, || {
3333 let counter_clone = counter_clone.clone();
3334 async move {
3335 counter_clone.fetch_add(1, std::sync::atomic::Ordering::SeqCst) as i64 + 200
3336 }
3337 })
3338 .await
3339 .unwrap();
3340 assert_eq!(val, 100);
3341
3342 assert_eq!(counter.load(std::sync::atomic::Ordering::SeqCst), 1);
3343 }
3344
3345 #[tokio::test]
3346 async fn test_cache_remember_async_cache_hit_returns_cached() {
3347 let cache = make_cache();
3348 cache.set("predefined_async", 42i64, None).unwrap();
3349
3350 let val: i64 = cache
3351 .remember_async("predefined_async", None, || async {
3352 panic!("callback should not be called on cache hit");
3353 })
3354 .await
3355 .unwrap();
3356 assert_eq!(val, 42);
3357 }
3358
3359 #[tokio::test]
3360 async fn test_cache_remember_async_writes_with_ttl() {
3361 let cache = make_cache();
3362 cache
3363 .remember_async("key_async", Some(Duration::from_millis(50)), || async {
3364 42i64
3365 })
3366 .await
3367 .unwrap();
3368
3369 assert_eq!(
3370 cache.get::<String>("key_async").unwrap(),
3371 Some("42".to_string())
3372 );
3373
3374 tokio::time::sleep(Duration::from_millis(100)).await;
3375 assert!(cache.get::<String>("key_async").unwrap().is_none());
3376 }
3377
3378 #[tokio::test]
3379 async fn test_cache_remember_async_releases_lock_on_success() {
3380 let cache = make_cache();
3381 cache
3382 .remember_async("key_async", None, || async { 42i64 })
3383 .await
3384 .unwrap();
3385 assert!(!cache.has("key_async_lock").unwrap());
3386 }
3387
3388 #[tokio::test]
3389 async fn test_cache_remember_async_lock_has_no_ttl_php_bug() {
3390 let cache = make_cache();
3391 cache
3392 .remember_async("key_async", None, || async { 42i64 })
3393 .await
3394 .unwrap();
3395 assert!(!cache.has("key_async_lock").unwrap());
3396 }
3397
3398 #[test]
3403 fn test_cache_with_store() {
3404 let cache = Cache::new();
3405 cache.register_store("redis", Box::new(MemoryCacheDriver::new()));
3406
3407 let result = cache
3408 .with_store("redis", |driver| {
3409 driver.set_raw("key", b"value".to_vec(), None)?;
3410 driver.get_raw("key")
3411 })
3412 .unwrap();
3413
3414 assert_eq!(result, Some(b"value".to_vec()));
3415 }
3416
3417 #[test]
3418 fn test_cache_with_store_not_found() {
3419 let cache = Cache::new();
3420 let result: Result<Option<Vec<u8>>, CacheError> =
3421 cache.with_store("nonexistent", |driver| driver.get_raw("key"));
3422 assert!(matches!(result, Err(CacheError::NotFound(_))));
3423 }
3424
3425 #[test]
3430 fn test_default_cache_singleton() {
3431 let c1 = default_cache();
3432 let c2 = default_cache();
3433 assert!(std::ptr::eq(c1, c2));
3435 }
3436
3437 #[test]
3445 fn test_r5_php_set_get_basic_alignment() {
3446 let cache = make_cache();
3451 cache.set("name", "Alice", None).unwrap();
3452 let val: String = cache.get("name").unwrap().unwrap();
3453 assert_eq!(val, "Alice");
3454 }
3455
3456 #[test]
3457 fn test_r5_php_is_numeric_short_circuit() {
3458 let cache = make_cache();
3463 cache.set("count", 42i64, None).unwrap();
3464
3465 let s: String = cache.get("count").unwrap().unwrap();
3467 assert_eq!(s, "42");
3468 }
3469
3470 #[test]
3471 fn test_r5_php_inc_no_serialize() {
3472 let cache = make_cache();
3475 cache.set("counter", 100i64, None).unwrap();
3476 let new_val = cache.inc("counter", 50).unwrap();
3477 assert_eq!(new_val, 150);
3478
3479 let s: String = cache.get("counter").unwrap().unwrap();
3481 assert_eq!(s, "150");
3482 }
3483
3484 #[test]
3485 fn test_r5_php_dec_no_serialize() {
3486 let cache = make_cache();
3488 cache.set("counter", 100i64, None).unwrap();
3489 let new_val = cache.dec("counter", 30).unwrap();
3490 assert_eq!(new_val, 70);
3491 }
3492
3493 #[test]
3494 fn test_r5_php_remember_lock_mechanism() {
3495 let cache = make_cache();
3498 let val: i64 = cache.remember("key", None, || 42).unwrap();
3499 assert_eq!(val, 42);
3500 assert_eq!(cache.get::<String>("key").unwrap(), Some("42".to_string()));
3501 assert!(!cache.has("key_lock").unwrap());
3503 }
3504
3505 #[test]
3506 fn test_r5_php_push_max_1000_array_shift() {
3507 let cache = make_cache();
3509 for i in 0..1001i64 {
3510 cache.push("list", i, None).unwrap();
3511 }
3512 let list: Vec<i64> = cache.get("list").unwrap().unwrap();
3513 assert_eq!(list.len(), 1000);
3514 assert_eq!(list[0], 1); assert_eq!(list[999], 1000);
3516 }
3517
3518 #[test]
3519 fn test_r5_php_push_array_unique() {
3520 let cache = make_cache();
3522 cache.push("list", "a".to_string(), None).unwrap();
3523 cache.push("list", "a".to_string(), None).unwrap();
3524 cache.push("list", "b".to_string(), None).unwrap();
3525 cache.push("list", "a".to_string(), None).unwrap();
3526
3527 let list: Vec<String> = cache.get("list").unwrap().unwrap();
3528 assert_eq!(list, vec!["a".to_string(), "b".to_string()]);
3529 }
3530
3531 #[test]
3532 fn test_r5_php_pull_get_then_delete() {
3533 let cache = make_cache();
3535 cache.set("key", "value", None).unwrap();
3536
3537 let val: Option<String> = cache.pull("key").unwrap();
3538 assert_eq!(val, Some("value".to_string()));
3539 assert!(!cache.has("key").unwrap());
3540 }
3541
3542 #[test]
3543 fn test_r5_php_delete_nonexistent_no_error() {
3544 let cache = make_cache();
3546 let result = cache.delete("nonexistent");
3547 assert!(result.is_ok());
3548 }
3549
3550 #[test]
3551 fn test_r5_php_has_ttl_expiration() {
3552 let cache = make_cache();
3554 cache
3555 .set("key", "value", Some(Duration::from_millis(50)))
3556 .unwrap();
3557 assert!(cache.has("key").unwrap());
3558
3559 std::thread::sleep(Duration::from_millis(100));
3560 assert!(!cache.has("key").unwrap());
3561 }
3562
3563 #[test]
3564 fn test_r5_php_clear_all_keys() {
3565 let cache = make_cache();
3567 cache.set("key1", "value1", None).unwrap();
3568 cache.set("key2", "value2", None).unwrap();
3569 cache.set("key3", "value3", None).unwrap();
3570
3571 cache.clear().unwrap();
3572
3573 assert!(!cache.has("key1").unwrap());
3574 assert!(!cache.has("key2").unwrap());
3575 assert!(!cache.has("key3").unwrap());
3576 }
3577
3578 #[test]
3583 fn test_php_bug_unserialize_numeric_returns_string() {
3584 let cache = make_cache();
3597
3598 cache.set("count", 42i64, None).unwrap();
3600
3601 let s: String = cache.get("count").unwrap().unwrap();
3603 assert_eq!(s, "42");
3604
3605 let n: i64 = s.parse().unwrap();
3607 assert_eq!(n, 42);
3608 }
3609
3610 #[test]
3611 fn test_php_bug_remember_lock_no_ttl() {
3612 let cache = make_cache();
3620 cache.remember("key", None, || 42i64).unwrap();
3621 assert!(!cache.has("key_lock").unwrap());
3623 }
3624
3625 #[test]
3626 fn test_php_bug_remember_has_get_double_check() {
3627 let cache = make_cache();
3644 let val: i64 = cache.remember("key", None, || 42).unwrap();
3645 assert_eq!(val, 42);
3646 }
3647
3648 #[test]
3649 fn test_php_behavior_set_overwrite() {
3650 let cache = make_cache();
3652 cache.set("key", "first", None).unwrap();
3653 cache.set("key", "second", None).unwrap();
3654
3655 let val: String = cache.get("key").unwrap().unwrap();
3656 assert_eq!(val, "second");
3657 }
3658
3659 #[test]
3660 fn test_php_behavior_ttl_permanent() {
3661 let cache = make_cache();
3663 cache.set("key", "value", None).unwrap();
3664
3665 assert!(cache.has("key").unwrap());
3667
3668 std::thread::sleep(Duration::from_millis(50));
3670 assert!(cache.has("key").unwrap());
3671 }
3672
3673 #[test]
3678 fn test_redis_config_default() {
3679 let config = RedisConfig::default();
3681 assert_eq!(config.host, "127.0.0.1");
3682 assert_eq!(config.port, 6379);
3683 assert_eq!(config.password, "");
3684 assert_eq!(config.select, 0);
3685 assert_eq!(config.timeout, Duration::ZERO);
3686 assert_eq!(config.expire, None);
3687 assert!(!config.persistent);
3688 assert_eq!(config.prefix, "");
3689 assert_eq!(config.tag_prefix, "tag:");
3690 }
3691
3692 #[test]
3693 fn test_redis_config_with_prefix() {
3694 let config = RedisConfig::with_prefix("myapp:");
3695 assert_eq!(config.prefix, "myapp:");
3696 assert_eq!(config.host, "127.0.0.1");
3697 assert_eq!(config.tag_prefix, "tag:");
3698 }
3699
3700 #[test]
3701 fn test_redis_config_with_expire() {
3702 let config = RedisConfig::with_expire(Duration::from_secs(3600));
3703 assert_eq!(config.expire, Some(Duration::from_secs(3600)));
3704 assert_eq!(config.prefix, "");
3705 }
3706
3707 #[test]
3712 fn test_mock_redis_set_get_roundtrip() {
3713 let backend = MockRedisBackend::new();
3714 backend.set("key1", b"value1".to_vec()).unwrap();
3715 let val = backend.get("key1").unwrap();
3716 assert_eq!(val, Some(b"value1".to_vec()));
3717 }
3718
3719 #[test]
3720 fn test_mock_redis_del() {
3721 let backend = MockRedisBackend::new();
3722 backend.set("key1", b"value1".to_vec()).unwrap();
3723 let removed = backend.del("key1").unwrap();
3724 assert_eq!(removed, 1);
3725 assert_eq!(backend.get("key1").unwrap(), None);
3726 assert_eq!(backend.del("key1").unwrap(), 0);
3728 }
3729
3730 #[test]
3731 fn test_mock_redis_exists() {
3732 let backend = MockRedisBackend::new();
3733 assert!(!backend.exists("key1").unwrap());
3734 backend.set("key1", b"value1".to_vec()).unwrap();
3735 assert!(backend.exists("key1").unwrap());
3736 }
3737
3738 #[test]
3739 fn test_mock_redis_incr_by_new_key() {
3740 let backend = MockRedisBackend::new();
3742 let result = backend.incr_by("counter", 5).unwrap();
3743 assert_eq!(result, 5);
3744 let val = backend.get("counter").unwrap();
3746 assert_eq!(val, Some(b"5".to_vec()));
3747 }
3748
3749 #[test]
3750 fn test_mock_redis_incr_by_existing_key() {
3751 let backend = MockRedisBackend::new();
3752 backend.set("counter", b"10".to_vec()).unwrap();
3753 let result = backend.incr_by("counter", 5).unwrap();
3754 assert_eq!(result, 15);
3755 let val = backend.get("counter").unwrap();
3756 assert_eq!(val, Some(b"15".to_vec()));
3757 }
3758
3759 #[test]
3760 fn test_mock_redis_incr_by_non_integer_error() {
3761 let backend = MockRedisBackend::new();
3763 backend.set("key", b"not_a_number".to_vec()).unwrap();
3764 let result = backend.incr_by("key", 1);
3765 assert!(result.is_err());
3766 }
3767
3768 #[test]
3769 fn test_mock_redis_decr_by() {
3770 let backend = MockRedisBackend::new();
3771 let result = backend.decr_by("counter", 3).unwrap();
3772 assert_eq!(result, -3);
3773 }
3774
3775 #[test]
3780 fn test_mock_redis_set_ex_and_expire() {
3781 let backend = MockRedisBackend::new();
3782 backend
3783 .set_ex("key1", b"value1".to_vec(), Duration::from_millis(50))
3784 .unwrap();
3785 assert!(backend.get("key1").unwrap().is_some());
3786 std::thread::sleep(Duration::from_millis(80));
3787 assert_eq!(backend.get("key1").unwrap(), None);
3788 }
3789
3790 #[test]
3791 fn test_mock_redis_expired_key_exists_false() {
3792 let backend = MockRedisBackend::new();
3793 backend
3794 .set_ex("key1", b"value1".to_vec(), Duration::from_millis(50))
3795 .unwrap();
3796 assert!(backend.exists("key1").unwrap());
3797 std::thread::sleep(Duration::from_millis(80));
3798 assert!(!backend.exists("key1").unwrap());
3799 }
3800
3801 #[test]
3806 fn test_mock_redis_sadd_smembers() {
3807 let backend = MockRedisBackend::new();
3808 backend.sadd("tag:users", "user:1").unwrap();
3809 backend.sadd("tag:users", "user:2").unwrap();
3810 backend.sadd("tag:users", "user:3").unwrap();
3811 let members = backend.smembers("tag:users").unwrap();
3812 assert_eq!(members.len(), 3);
3813 assert!(members.contains(&"user:1".to_string()));
3814 assert!(members.contains(&"user:2".to_string()));
3815 assert!(members.contains(&"user:3".to_string()));
3816 }
3817
3818 #[test]
3819 fn test_mock_redis_sadd_dedup() {
3820 let backend = MockRedisBackend::new();
3822 let added1 = backend.sadd("tag:users", "user:1").unwrap();
3823 assert_eq!(added1, 1);
3824 let added2 = backend.sadd("tag:users", "user:1").unwrap();
3825 assert_eq!(added2, 0);
3826 let members = backend.smembers("tag:users").unwrap();
3827 assert_eq!(members.len(), 1);
3828 }
3829
3830 #[test]
3831 fn test_mock_redis_smembers_nonexistent_key() {
3832 let backend = MockRedisBackend::new();
3834 let members = backend.smembers("nonexistent").unwrap();
3835 assert!(members.is_empty());
3836 }
3837
3838 #[test]
3843 fn test_mock_redis_flush_db() {
3844 let backend = MockRedisBackend::new();
3845 backend.set("key1", b"v1".to_vec()).unwrap();
3846 backend.set("key2", b"v2".to_vec()).unwrap();
3847 backend.sadd("tag:1", "m1").unwrap();
3848 backend.flush_db().unwrap();
3849 assert_eq!(backend.get("key1").unwrap(), None);
3850 assert_eq!(backend.get("key2").unwrap(), None);
3851 assert!(backend.smembers("tag:1").unwrap().is_empty());
3852 }
3853
3854 #[test]
3855 fn test_mock_redis_del_many() {
3856 let backend = MockRedisBackend::new();
3857 backend.set("key1", b"v1".to_vec()).unwrap();
3858 backend.set("key2", b"v2".to_vec()).unwrap();
3859 backend.set("key3", b"v3".to_vec()).unwrap();
3860 let removed = backend.del_many(&["key1", "key2", "nonexistent"]).unwrap();
3861 assert_eq!(removed, 2);
3862 assert_eq!(backend.get("key1").unwrap(), None);
3863 assert_eq!(backend.get("key2").unwrap(), None);
3864 assert!(backend.get("key3").unwrap().is_some());
3865 }
3866
3867 fn make_redis_driver() -> RedisCacheDriver {
3873 RedisCacheDriver::new(RedisConfig::default())
3874 }
3875
3876 #[test]
3877 fn test_redis_driver_set_get_roundtrip() {
3878 let driver = make_redis_driver();
3879 driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
3880 let val = driver.get_raw("key1").unwrap();
3881 assert_eq!(val, Some(b"value1".to_vec()));
3882 }
3883
3884 #[test]
3885 fn test_redis_driver_delete() {
3886 let driver = make_redis_driver();
3887 driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
3888 driver.delete("key1").unwrap();
3889 assert_eq!(driver.get_raw("key1").unwrap(), None);
3890 }
3891
3892 #[test]
3893 fn test_redis_driver_has() {
3894 let driver = make_redis_driver();
3895 assert!(!driver.has("key1").unwrap());
3896 driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
3897 assert!(driver.has("key1").unwrap());
3898 }
3899
3900 #[test]
3901 fn test_redis_driver_clear() {
3902 let driver = make_redis_driver();
3903 driver.set_raw("key1", b"v1".to_vec(), None).unwrap();
3904 driver.set_raw("key2", b"v2".to_vec(), None).unwrap();
3905 driver.clear().unwrap();
3906 assert_eq!(driver.get_raw("key1").unwrap(), None);
3907 assert_eq!(driver.get_raw("key2").unwrap(), None);
3908 }
3909
3910 #[test]
3911 fn test_redis_driver_inc_dec() {
3912 let driver = make_redis_driver();
3913 let result = driver.inc("counter", 5).unwrap();
3915 assert_eq!(result, 5);
3916 let result = driver.inc("counter", 3).unwrap();
3917 assert_eq!(result, 8);
3918 let result = driver.dec("counter", 2).unwrap();
3919 assert_eq!(result, 6);
3920 }
3921
3922 #[test]
3927 fn test_redis_driver_cache_key_with_prefix() {
3928 let driver = RedisCacheDriver::new(RedisConfig::with_prefix("myapp:"));
3930 assert_eq!(driver.cache_key("user:1"), "myapp:user:1");
3931 }
3932
3933 #[test]
3934 fn test_redis_driver_cache_key_no_prefix() {
3935 let driver = RedisCacheDriver::new(RedisConfig::default());
3936 assert_eq!(driver.cache_key("user:1"), "user:1");
3937 }
3938
3939 #[test]
3940 fn test_redis_driver_tag_key_md5() {
3941 let driver = RedisCacheDriver::new(RedisConfig::default());
3943 let tag_key = driver.tag_key("users");
3944 let expected_md5 = compute_md5("users");
3945 assert_eq!(tag_key, format!("tag:{}", expected_md5));
3946 }
3947
3948 #[test]
3949 fn test_redis_driver_tag_key_custom_prefix() {
3950 let config = RedisConfig {
3951 tag_prefix: "t:".to_string(),
3952 ..RedisConfig::default()
3953 };
3954 let driver = RedisCacheDriver::new(config);
3955 let tag_key = driver.tag_key("users");
3956 let expected_md5 = compute_md5("users");
3957 assert_eq!(tag_key, format!("t:{}", expected_md5));
3958 }
3959
3960 #[test]
3965 fn test_redis_driver_prefix_applied_to_set() {
3966 let driver = RedisCacheDriver::new(RedisConfig::with_prefix("myapp:"));
3968 driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
3969 let val = driver.backend().get("myapp:key1").unwrap();
3971 assert_eq!(val, Some(b"value1".to_vec()));
3972 assert_eq!(driver.backend().get("key1").unwrap(), None);
3974 }
3975
3976 #[test]
3977 fn test_redis_driver_prefix_applied_to_get() {
3978 let driver = RedisCacheDriver::new(RedisConfig::with_prefix("myapp:"));
3979 driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
3980 let val = driver.get_raw("key1").unwrap();
3981 assert_eq!(val, Some(b"value1".to_vec()));
3982 }
3983
3984 #[test]
3985 fn test_redis_driver_prefix_applied_to_delete() {
3986 let driver = RedisCacheDriver::new(RedisConfig::with_prefix("myapp:"));
3987 driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
3988 driver.delete("key1").unwrap();
3989 assert_eq!(driver.backend().get("myapp:key1").unwrap(), None);
3990 }
3991
3992 #[test]
3993 fn test_redis_driver_prefix_applied_to_has() {
3994 let driver = RedisCacheDriver::new(RedisConfig::with_prefix("myapp:"));
3995 driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
3996 assert!(driver.has("key1").unwrap());
3997 assert!(driver.backend().exists("myapp:key1").unwrap());
3998 }
3999
4000 #[test]
4001 fn test_redis_driver_prefix_applied_to_inc() {
4002 let driver = RedisCacheDriver::new(RedisConfig::with_prefix("myapp:"));
4003 let result = driver.inc("counter", 5).unwrap();
4004 assert_eq!(result, 5);
4005 let val = driver.backend().get("myapp:counter").unwrap();
4006 assert_eq!(val, Some(b"5".to_vec()));
4007 }
4008
4009 #[test]
4014 fn test_redis_driver_append_and_get_tag_items() {
4015 let driver = make_redis_driver();
4017 driver.append("tag:users", "user:1").unwrap();
4018 driver.append("tag:users", "user:2").unwrap();
4019 driver.append("tag:users", "user:3").unwrap();
4020 let members = driver.backend().smembers("tag:users").unwrap();
4021 assert_eq!(members.len(), 3);
4022 }
4023
4024 #[test]
4025 fn test_redis_driver_get_tag_items_with_tag_key() {
4026 let driver = make_redis_driver();
4028 let tag_name = driver.tag_key("users");
4029 driver.append(&tag_name, "user:1").unwrap();
4030 driver.append(&tag_name, "user:2").unwrap();
4031 let members = driver.get_tag_items("users").unwrap();
4032 assert_eq!(members.len(), 2);
4033 assert!(members.contains(&"user:1".to_string()));
4034 assert!(members.contains(&"user:2".to_string()));
4035 }
4036
4037 #[test]
4038 fn test_redis_driver_clear_tag() {
4039 let driver = make_redis_driver();
4040 driver.set_raw("key1", b"v1".to_vec(), None).unwrap();
4041 driver.set_raw("key2", b"v2".to_vec(), None).unwrap();
4042 driver.clear_tag(&["key1", "key2"]).unwrap();
4043 assert_eq!(driver.get_raw("key1").unwrap(), None);
4044 assert_eq!(driver.get_raw("key2").unwrap(), None);
4045 }
4046
4047 #[test]
4052 fn test_redis_driver_set_with_ttl_uses_setex() {
4053 let driver = make_redis_driver();
4055 driver
4056 .set_raw("key1", b"value1".to_vec(), Some(Duration::from_millis(100)))
4057 .unwrap();
4058 assert!(driver.get_raw("key1").unwrap().is_some());
4059 std::thread::sleep(Duration::from_millis(150));
4060 assert_eq!(driver.get_raw("key1").unwrap(), None);
4061 }
4062
4063 #[test]
4064 fn test_redis_driver_set_without_ttl_uses_set() {
4065 let driver = make_redis_driver();
4067 driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
4068 std::thread::sleep(Duration::from_millis(50));
4069 assert!(driver.get_raw("key1").unwrap().is_some());
4070 }
4071
4072 #[test]
4073 fn test_redis_driver_set_with_config_expire() {
4074 let config = RedisConfig::with_expire(Duration::from_millis(100));
4076 let driver = RedisCacheDriver::new(config);
4077 driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
4078 assert!(driver.get_raw("key1").unwrap().is_some());
4079 std::thread::sleep(Duration::from_millis(150));
4080 assert_eq!(driver.get_raw("key1").unwrap(), None);
4081 }
4082
4083 #[test]
4084 fn test_redis_driver_set_ttl_overrides_config_expire() {
4085 let config = RedisConfig::with_expire(Duration::from_secs(3600));
4087 let driver = RedisCacheDriver::new(config);
4088 driver
4089 .set_raw("key1", b"value1".to_vec(), Some(Duration::from_millis(50)))
4090 .unwrap();
4091 std::thread::sleep(Duration::from_millis(80));
4092 assert_eq!(driver.get_raw("key1").unwrap(), None);
4093 }
4094
4095 #[test]
4100 fn test_redis_driver_with_cache_facade() {
4101 let cache = Cache::new();
4103 let driver = RedisCacheDriver::new(RedisConfig::default());
4104 cache.register_store("redis", Box::new(driver));
4105 cache.set_default_store("redis").unwrap();
4106 cache.set("key", "value", None).unwrap();
4107 let val: String = cache.get("key").unwrap().unwrap();
4108 assert_eq!(val, "value");
4109 }
4110
4111 #[test]
4112 fn test_redis_driver_with_cache_facade_inc() {
4113 let cache = Cache::new();
4115 let driver = RedisCacheDriver::new(RedisConfig::default());
4116 cache.register_store("redis", Box::new(driver));
4117 cache.set_default_store("redis").unwrap();
4118 let result = cache.inc("counter", 5).unwrap();
4119 assert_eq!(result, 5);
4120 let result = cache.inc("counter", 3).unwrap();
4121 assert_eq!(result, 8);
4122 }
4123
4124 #[test]
4129 fn test_php_redis_inc_not_through_serialize() {
4130 let driver = make_redis_driver();
4135 driver.inc("counter", 5).unwrap();
4136 let val = driver.backend().get(&driver.cache_key("counter")).unwrap();
4137 assert_eq!(val, Some(b"5".to_vec())); assert_ne!(val, Some(b"i:5;".to_vec())); }
4140
4141 #[test]
4142 fn test_php_redis_set_with_ttl_expires() {
4143 let driver = make_redis_driver();
4145 driver
4146 .set_raw("key", b"value".to_vec(), Some(Duration::from_millis(50)))
4147 .unwrap();
4148 assert!(driver.get_raw("key").unwrap().is_some());
4149 std::thread::sleep(Duration::from_millis(80));
4150 assert_eq!(driver.get_raw("key").unwrap(), None);
4151 }
4152
4153 #[test]
4154 fn test_php_redis_set_without_ttl_permanent() {
4155 let driver = make_redis_driver();
4157 driver.set_raw("key", b"value".to_vec(), None).unwrap();
4158 std::thread::sleep(Duration::from_millis(50));
4159 assert!(driver.get_raw("key").unwrap().is_some());
4160 }
4161
4162 #[test]
4163 fn test_php_redis_tag_key_format() {
4164 let driver = make_redis_driver();
4166 let tag_key = driver.tag_key("users");
4167 let expected = format!("tag:{}", compute_md5("users"));
4168 assert_eq!(tag_key, expected);
4169 assert_eq!(compute_md5("users").len(), 32);
4170 }
4171
4172 #[test]
4173 fn test_php_redis_clear_uses_flushdb() {
4174 let driver = make_redis_driver();
4176 driver.set_raw("key1", b"v1".to_vec(), None).unwrap();
4177 driver.set_raw("key2", b"v2".to_vec(), None).unwrap();
4178 driver.append("tag:1", "m1").unwrap();
4179 driver.clear().unwrap();
4180 assert_eq!(driver.get_raw("key1").unwrap(), None);
4181 assert_eq!(driver.get_raw("key2").unwrap(), None);
4182 assert!(driver.backend().smembers("tag:1").unwrap().is_empty());
4183 }
4184
4185 #[test]
4186 fn test_php_redis_inc_returns_new_value() {
4187 let driver = make_redis_driver();
4189 let r1 = driver.inc("c", 1).unwrap();
4190 assert_eq!(r1, 1);
4191 let r2 = driver.inc("c", 1).unwrap();
4192 assert_eq!(r2, 2);
4193 let r3 = driver.inc("c", 10).unwrap();
4194 assert_eq!(r3, 12);
4195 let r4 = driver.dec("c", 5).unwrap();
4196 assert_eq!(r4, 7);
4197 }
4198
4199 #[test]
4200 fn test_php_redis_delete_nonexistent_returns_ok() {
4201 let driver = make_redis_driver();
4203 driver.delete("nonexistent").unwrap();
4204 }
4205
4206 #[test]
4207 fn test_php_redis_md5_alignment() {
4208 assert_eq!(compute_md5("hello"), "5d41402abc4b2a76b9719d911017c592");
4211 assert_eq!(compute_md5(""), "d41d8cd98f00b204e9800998ecf8427e");
4213 assert_eq!(compute_md5("users").len(), 32);
4214 }
4215
4216 #[test]
4217 fn test_php_redis_append_uses_sadd() {
4218 let driver = make_redis_driver();
4221 driver.append("tag:1", "m1").unwrap();
4222 driver.append("tag:1", "m1").unwrap(); driver.append("tag:1", "m2").unwrap();
4224 let members = driver.backend().smembers("tag:1").unwrap();
4225 assert_eq!(members.len(), 2);
4227 }
4228
4229 #[test]
4230 fn test_php_redis_config_precedence_ttl() {
4231 let config = RedisConfig::with_expire(Duration::from_secs(3600));
4234 let driver = RedisCacheDriver::new(config);
4235 driver
4236 .set_raw("key1", b"v1".to_vec(), Some(Duration::from_millis(50)))
4237 .unwrap();
4238 std::thread::sleep(Duration::from_millis(80));
4239 assert_eq!(driver.get_raw("key1").unwrap(), None); let config = RedisConfig::with_expire(Duration::from_millis(50));
4243 let driver = RedisCacheDriver::new(config);
4244 driver.set_raw("key2", b"v2".to_vec(), None).unwrap();
4245 std::thread::sleep(Duration::from_millis(80));
4246 assert_eq!(driver.get_raw("key2").unwrap(), None); let driver = make_redis_driver();
4250 driver.set_raw("key3", b"v3".to_vec(), None).unwrap();
4251 std::thread::sleep(Duration::from_millis(50));
4252 assert!(driver.get_raw("key3").unwrap().is_some()); }
4254
4255 #[test]
4260 fn test_multi_level_driver_set_get() {
4261 let l1 = sz_orm_core::MemoryCache::new();
4262 let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4263
4264 driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
4265 let val = driver.get_raw("key1").unwrap();
4266 assert_eq!(val, Some(b"value1".to_vec()));
4267 }
4268
4269 #[test]
4270 fn test_multi_level_driver_delete() {
4271 let l1 = sz_orm_core::MemoryCache::new();
4272 let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4273
4274 driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
4275 driver.delete("key1").unwrap();
4276 assert_eq!(driver.get_raw("key1").unwrap(), None);
4277 }
4278
4279 #[test]
4280 fn test_multi_level_driver_has() {
4281 let l1 = sz_orm_core::MemoryCache::new();
4282 let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4283
4284 assert!(!driver.has("key1").unwrap());
4285 driver.set_raw("key1", b"value1".to_vec(), None).unwrap();
4286 assert!(driver.has("key1").unwrap());
4287 }
4288
4289 #[test]
4290 fn test_multi_level_driver_clear() {
4291 let l1 = sz_orm_core::MemoryCache::new();
4292 let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4293
4294 driver.set_raw("key1", b"v1".to_vec(), None).unwrap();
4295 driver.set_raw("key2", b"v2".to_vec(), None).unwrap();
4296 driver.clear().unwrap();
4297 assert_eq!(driver.get_raw("key1").unwrap(), None);
4298 assert_eq!(driver.get_raw("key2").unwrap(), None);
4299 }
4300
4301 #[test]
4306 fn test_multi_level_two_levels_cascade_get() {
4307 let l1 = sz_orm_core::MemoryCache::new();
4309 let l2 = sz_orm_core::MemoryCache::new();
4310
4311 l2.set("key", b"from_l2".to_vec(), None).unwrap();
4313
4314 let driver = MultiLevelCacheDriver::new()
4315 .add_level(Box::new(l1.clone()))
4316 .add_level(Box::new(l2));
4317
4318 let val = driver.get_raw("key").unwrap();
4320 assert_eq!(val, Some(b"from_l2".to_vec()));
4321
4322 let l1_val = l1.get("key").unwrap();
4324 assert_eq!(l1_val, Some(b"from_l2".to_vec()));
4325 }
4326
4327 #[test]
4328 fn test_multi_level_set_writes_all_levels() {
4329 let l1 = sz_orm_core::MemoryCache::new();
4330 let l2 = sz_orm_core::MemoryCache::new();
4331
4332 let driver = MultiLevelCacheDriver::new()
4333 .add_level(Box::new(l1.clone()))
4334 .add_level(Box::new(l2.clone()));
4335
4336 driver.set_raw("key", b"value".to_vec(), None).unwrap();
4337
4338 assert_eq!(l1.get("key").unwrap(), Some(b"value".to_vec()));
4340 assert_eq!(l2.get("key").unwrap(), Some(b"value".to_vec()));
4341 }
4342
4343 #[test]
4344 fn test_multi_level_delete_removes_all_levels() {
4345 let l1 = sz_orm_core::MemoryCache::new();
4346 let l2 = sz_orm_core::MemoryCache::new();
4347
4348 let driver = MultiLevelCacheDriver::new()
4349 .add_level(Box::new(l1.clone()))
4350 .add_level(Box::new(l2.clone()));
4351
4352 driver.set_raw("key", b"value".to_vec(), None).unwrap();
4353 driver.delete("key").unwrap();
4354
4355 assert_eq!(l1.get("key").unwrap(), None);
4356 assert_eq!(l2.get("key").unwrap(), None);
4357 }
4358
4359 #[test]
4360 fn test_multi_level_l1_hit_skips_l2() {
4361 let l1 = sz_orm_core::MemoryCache::new();
4363 let l2 = sz_orm_core::MemoryCache::new();
4364
4365 l1.set("key", b"from_l1".to_vec(), None).unwrap();
4366 l2.set("key", b"from_l2".to_vec(), None).unwrap();
4367
4368 let driver = MultiLevelCacheDriver::new()
4369 .add_level(Box::new(l1))
4370 .add_level(Box::new(l2));
4371
4372 let val = driver.get_raw("key").unwrap();
4373 assert_eq!(val, Some(b"from_l1".to_vec()));
4374 }
4375
4376 #[test]
4381 fn test_multi_level_driver_inc_initial_value() {
4382 let l1 = sz_orm_core::MemoryCache::new();
4383 let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4384
4385 let new_val = driver.inc("counter", 1).unwrap();
4386 assert_eq!(new_val, 1);
4387
4388 let val = driver.get_raw("counter").unwrap();
4389 assert_eq!(val, Some(b"1".to_vec()));
4390 }
4391
4392 #[test]
4393 fn test_multi_level_driver_inc_accumulate() {
4394 let l1 = sz_orm_core::MemoryCache::new();
4395 let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4396
4397 driver.inc("counter", 5).unwrap();
4398 driver.inc("counter", 3).unwrap();
4399 driver.inc("counter", 1).unwrap();
4400
4401 let val = driver.get_raw("counter").unwrap();
4402 assert_eq!(val, Some(b"9".to_vec()));
4403 }
4404
4405 #[test]
4406 fn test_multi_level_driver_dec() {
4407 let l1 = sz_orm_core::MemoryCache::new();
4408 let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4409
4410 driver.set_raw("counter", b"10".to_vec(), None).unwrap();
4411 let new_val = driver.dec("counter", 3).unwrap();
4412 assert_eq!(new_val, 7);
4413
4414 let val = driver.get_raw("counter").unwrap();
4415 assert_eq!(val, Some(b"7".to_vec()));
4416 }
4417
4418 #[test]
4419 fn test_multi_level_driver_inc_preserves_ttl() {
4420 let l1 = sz_orm_core::MemoryCache::new();
4422 let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4423
4424 driver
4425 .set_raw("counter", b"5".to_vec(), Some(Duration::from_millis(200)))
4426 .unwrap();
4427
4428 let ttl_before = driver.inner().ttl("counter").unwrap();
4430 assert!(ttl_before.is_some());
4431
4432 driver.inc("counter", 1).unwrap();
4433
4434 let ttl_after = driver.inner().ttl("counter").unwrap();
4436 assert!(ttl_after.is_some());
4437 }
4438
4439 #[test]
4444 fn test_multi_level_driver_ttl_expiration() {
4445 let l1 = sz_orm_core::MemoryCache::new();
4446 let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4447
4448 driver
4449 .set_raw("key", b"value".to_vec(), Some(Duration::from_millis(50)))
4450 .unwrap();
4451 assert!(driver.get_raw("key").unwrap().is_some());
4452
4453 std::thread::sleep(Duration::from_millis(80));
4454 assert_eq!(driver.get_raw("key").unwrap(), None);
4455 }
4456
4457 #[test]
4458 fn test_multi_level_driver_has_checks_ttl() {
4459 let l1 = sz_orm_core::MemoryCache::new();
4460 let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4461
4462 driver
4463 .set_raw("key", b"value".to_vec(), Some(Duration::from_millis(50)))
4464 .unwrap();
4465 assert!(driver.has("key").unwrap());
4466
4467 std::thread::sleep(Duration::from_millis(80));
4468 assert!(!driver.has("key").unwrap());
4469 }
4470
4471 #[test]
4476 fn test_multi_level_driver_with_cache_facade() {
4477 let l1 = sz_orm_core::MemoryCache::new();
4478 let l2 = sz_orm_core::MemoryCache::new();
4479 let driver = MultiLevelCacheDriver::new()
4480 .add_level(Box::new(l1))
4481 .add_level(Box::new(l2));
4482
4483 let cache = Cache::new();
4484 cache.register_store("default", Box::new(driver));
4485
4486 cache.set("user:1", "Alice", None).unwrap();
4487 assert_eq!(
4488 cache.get::<String>("user:1").unwrap(),
4489 Some("Alice".to_string())
4490 );
4491
4492 cache.delete("user:1").unwrap();
4493 assert_eq!(cache.get::<String>("user:1").unwrap(), None);
4494 }
4495
4496 #[test]
4497 fn test_multi_level_driver_with_cache_facade_inc() {
4498 let l1 = sz_orm_core::MemoryCache::new();
4499 let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4500
4501 let cache = Cache::new();
4502 cache.register_store("default", Box::new(driver));
4503
4504 cache.inc("counter", 5).unwrap();
4505 cache.inc("counter", 3).unwrap();
4506
4507 let val = cache.get::<String>("counter").unwrap();
4510 assert_eq!(val, Some("8".to_string()));
4511 }
4512
4513 #[test]
4518 fn test_multi_level_driver_empty_levels_get_returns_none() {
4519 let driver = MultiLevelCacheDriver::new();
4521 assert_eq!(driver.get_raw("key").unwrap(), None);
4522 }
4523
4524 #[test]
4525 fn test_multi_level_driver_empty_levels_has_returns_false() {
4526 let driver = MultiLevelCacheDriver::new();
4527 assert!(!driver.has("key").unwrap());
4528 }
4529
4530 #[test]
4531 fn test_multi_level_driver_inc_non_numeric_value_resets_to_step() {
4532 let l1 = sz_orm_core::MemoryCache::new();
4534 let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4535
4536 driver
4537 .set_raw("counter", b"not_a_number".to_vec(), None)
4538 .unwrap();
4539 let new_val = driver.inc("counter", 5).unwrap();
4540 assert_eq!(new_val, 5);
4541 }
4542
4543 #[test]
4544 fn test_multi_level_driver_default_impl() {
4545 let driver = MultiLevelCacheDriver::default();
4547 assert_eq!(driver.get_raw("key").unwrap(), None);
4548 }
4549
4550 #[test]
4555 fn test_r5_multi_level_get_set_basic() {
4556 let l1 = sz_orm_core::MemoryCache::new();
4558 let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4559
4560 driver.set_raw("key", b"value".to_vec(), None).unwrap();
4561 assert_eq!(driver.get_raw("key").unwrap(), Some(b"value".to_vec()));
4562 }
4563
4564 #[test]
4565 fn test_r5_multi_level_delete_nonexistent_no_error() {
4566 let l1 = sz_orm_core::MemoryCache::new();
4568 let driver = MultiLevelCacheDriver::new().add_level(Box::new(l1));
4569
4570 assert!(driver.delete("nonexistent").is_ok());
4571 }
4572
4573 #[test]
4574 fn test_r5_multi_level_clear_empties_all() {
4575 let l1 = sz_orm_core::MemoryCache::new();
4577 let l2 = sz_orm_core::MemoryCache::new();
4578 let driver = MultiLevelCacheDriver::new()
4579 .add_level(Box::new(l1))
4580 .add_level(Box::new(l2));
4581
4582 driver.set_raw("k1", b"v1".to_vec(), None).unwrap();
4583 driver.set_raw("k2", b"v2".to_vec(), None).unwrap();
4584 driver.clear().unwrap();
4585
4586 assert_eq!(driver.get_raw("k1").unwrap(), None);
4587 assert_eq!(driver.get_raw("k2").unwrap(), None);
4588 }
4589
4590 #[test]
4591 fn test_r5_multi_level_cascade_fill_back() {
4592 let l1 = sz_orm_core::MemoryCache::new();
4594 let l2 = sz_orm_core::MemoryCache::new();
4595
4596 l2.set("key", b"from_l2".to_vec(), None).unwrap();
4598
4599 let driver = MultiLevelCacheDriver::new()
4600 .add_level(Box::new(l1.clone()))
4601 .add_level(Box::new(l2));
4602
4603 let val = driver.get_raw("key").unwrap();
4605 assert_eq!(val, Some(b"from_l2".to_vec()));
4606
4607 assert_eq!(l1.get("key").unwrap(), Some(b"from_l2".to_vec()));
4609 }
4610
4611 #[test]
4616 fn test_tag_get_cache_key_default_no_prefix() {
4617 let driver = MemoryCacheDriver::new();
4619 assert_eq!(driver.get_cache_key("user:1"), "user:1");
4620 assert_eq!(driver.get_cache_key("hello"), "hello");
4621 }
4622
4623 #[test]
4624 fn test_tag_get_tag_key_default_format() {
4625 let driver = MemoryCacheDriver::new();
4627 let tag_key = driver.get_tag_key("user");
4628 assert_eq!(tag_key, "tag:ee11cbb19052e40b07aac0ca060c23ee");
4630 }
4631
4632 #[test]
4633 fn test_tag_append_creates_new_tag_set() {
4634 let driver = MemoryCacheDriver::new();
4636 driver.tag_append("tag:abc123", "user:1").unwrap();
4637 let storage_key = "tag:abc123"; let raw = driver.get_raw(storage_key).unwrap();
4640 let stored: Vec<String> = serde_json::from_slice(&raw.unwrap()).unwrap();
4641 assert_eq!(stored, vec!["user:1"]);
4642 }
4643
4644 #[test]
4645 fn test_tag_append_appends_to_existing() {
4646 let driver = MemoryCacheDriver::new();
4647 driver.tag_append("tag:abc", "key1").unwrap();
4648 driver.tag_append("tag:abc", "key2").unwrap();
4649 let storage_key = "tag:abc";
4650 let raw = driver.get_raw(storage_key).unwrap();
4651 let stored: Vec<String> = serde_json::from_slice(&raw.unwrap()).unwrap();
4652 assert_eq!(stored, vec!["key1", "key2"]);
4653 }
4654
4655 #[test]
4656 fn test_tag_append_dedup() {
4657 let driver = MemoryCacheDriver::new();
4659 driver.tag_append("tag:abc", "key1").unwrap();
4660 driver.tag_append("tag:abc", "key1").unwrap(); let storage_key = "tag:abc";
4662 let raw = driver.get_raw(storage_key).unwrap();
4663 let stored: Vec<String> = serde_json::from_slice(&raw.unwrap()).unwrap();
4664 assert_eq!(stored, vec!["key1"]);
4665 }
4666
4667 #[test]
4668 fn test_tag_append_max_1000_cap() {
4669 let driver = MemoryCacheDriver::new();
4671 for i in 0..1001i64 {
4672 driver.tag_append("tag:abc", &format!("key{}", i)).unwrap();
4673 }
4674 let storage_key = "tag:abc";
4675 let raw = driver.get_raw(storage_key).unwrap();
4676 let stored: Vec<String> = serde_json::from_slice(&raw.unwrap()).unwrap();
4677 assert_eq!(stored.len(), 1000);
4679 assert!(!stored.contains(&"key0".to_string()));
4680 assert!(stored.contains(&"key1".to_string()));
4681 assert!(stored.contains(&"key1000".to_string()));
4682 }
4683
4684 #[test]
4685 fn test_tag_items_empty_returns_empty() {
4686 let driver = MemoryCacheDriver::new();
4687 let items = driver.tag_items("nonexistent_tag").unwrap();
4688 assert!(items.is_empty());
4689 }
4690
4691 #[test]
4692 fn test_tag_items_returns_stored_keys() {
4693 let driver = MemoryCacheDriver::new();
4694 let tag_key = driver.get_tag_key("mytag");
4696 driver.tag_append(&tag_key, "key1").unwrap();
4697 driver.tag_append(&tag_key, "key2").unwrap();
4698 let items = driver.tag_items("mytag").unwrap();
4699 assert_eq!(items, vec!["key1", "key2"]);
4700 }
4701
4702 #[test]
4703 fn test_tag_clear_deletes_keys() {
4704 let driver = MemoryCacheDriver::new();
4705 driver.set_raw("key1", b"v1".to_vec(), None).unwrap();
4707 driver.set_raw("key2", b"v2".to_vec(), None).unwrap();
4708 driver
4710 .tag_clear(&["key1".to_string(), "key2".to_string()])
4711 .unwrap();
4712 assert!(!driver.has("key1").unwrap());
4713 assert!(!driver.has("key2").unwrap());
4714 }
4715
4716 #[test]
4717 fn test_tag_clear_empty_no_error() {
4718 let driver = MemoryCacheDriver::new();
4719 driver.tag_clear(&[]).unwrap();
4721 }
4722
4723 #[test]
4728 fn test_redis_tag_get_cache_key_with_prefix() {
4729 let config = RedisConfig {
4730 prefix: "myapp:".to_string(),
4731 ..RedisConfig::default()
4732 };
4733 let driver = RedisCacheDriver::new(config);
4734 assert_eq!(driver.get_cache_key("user:1"), "myapp:user:1");
4735 }
4736
4737 #[test]
4738 fn test_redis_tag_get_tag_key_with_tag_prefix() {
4739 let config = RedisConfig {
4740 tag_prefix: "tag:".to_string(),
4741 ..RedisConfig::default()
4742 };
4743 let driver = RedisCacheDriver::new(config);
4744 let tag_key = driver.get_tag_key("user");
4745 assert_eq!(tag_key, "tag:ee11cbb19052e40b07aac0ca060c23ee");
4747 }
4748
4749 #[test]
4750 fn test_redis_tag_get_tag_key_custom_prefix() {
4751 let config = RedisConfig {
4752 tag_prefix: "t:".to_string(),
4753 ..RedisConfig::default()
4754 };
4755 let driver = RedisCacheDriver::new(config);
4756 let tag_key = driver.get_tag_key("user");
4757 assert_eq!(tag_key, "t:ee11cbb19052e40b07aac0ca060c23ee");
4758 }
4759
4760 #[test]
4761 fn test_redis_tag_append_uses_sadd() {
4762 let driver = RedisCacheDriver::new(RedisConfig::default());
4764 let tag_key = driver.get_tag_key("mytag");
4765 driver.tag_append(&tag_key, "key1").unwrap();
4766 driver.tag_append(&tag_key, "key2").unwrap();
4767 driver.tag_append(&tag_key, "key1").unwrap(); let items = driver.tag_items("mytag").unwrap();
4769 assert_eq!(items.len(), 2);
4771 assert!(items.contains(&"key1".to_string()));
4772 assert!(items.contains(&"key2".to_string()));
4773 }
4774
4775 #[test]
4776 fn test_redis_tag_items_uses_smembers() {
4777 let driver = RedisCacheDriver::new(RedisConfig::default());
4778 let tag_key = driver.get_tag_key("mytag");
4779 driver.tag_append(&tag_key, "a").unwrap();
4780 driver.tag_append(&tag_key, "b").unwrap();
4781 driver.tag_append(&tag_key, "c").unwrap();
4782 let items = driver.tag_items("mytag").unwrap();
4783 assert_eq!(items.len(), 3);
4784 }
4785
4786 #[test]
4787 fn test_redis_tag_clear_does_not_double_prefix() {
4788 let config = RedisConfig {
4790 prefix: "app:".to_string(),
4791 ..RedisConfig::default()
4792 };
4793 let driver = RedisCacheDriver::new(config);
4794 driver.set_raw("key1", b"v1".to_vec(), None).unwrap();
4796 let tag_key = driver.get_tag_key("mytag");
4798 driver.tag_append(&tag_key, "app:key1").unwrap();
4799 let items = driver.tag_items("mytag").unwrap();
4800 assert_eq!(items, vec!["app:key1"]);
4801 driver.tag_clear(&items).unwrap();
4803 assert!(!driver.has("key1").unwrap());
4804 }
4805
4806 #[test]
4807 fn test_redis_tag_clear_empty_no_error() {
4808 let driver = RedisCacheDriver::new(RedisConfig::default());
4809 driver.tag_clear(&[]).unwrap();
4810 }
4811
4812 #[test]
4817 fn test_tagset_set_stores_value_and_appends_tag() {
4818 let cache = Cache::new();
4819 cache.register_default(MemoryCacheDriver::new());
4820
4821 cache.tag("user").set("user:1", "Alice", None).unwrap();
4823
4824 assert_eq!(
4826 cache.get::<String>("user:1").unwrap(),
4827 Some("Alice".to_string())
4828 );
4829
4830 let mgr = cache.manager.read();
4832 let driver = mgr.default_store().unwrap();
4833 let items = driver.tag_items("user").unwrap();
4834 assert_eq!(items, vec!["user:1"]);
4835 }
4836
4837 #[test]
4838 fn test_tagset_set_multiple_keys_same_tag() {
4839 let cache = Cache::new();
4840 cache.register_default(MemoryCacheDriver::new());
4841
4842 cache.tag("user").set("user:1", "Alice", None).unwrap();
4843 cache.tag("user").set("user:2", "Bob", None).unwrap();
4844 cache.tag("user").set("user:3", "Carol", None).unwrap();
4845
4846 let mgr = cache.manager.read();
4847 let driver = mgr.default_store().unwrap();
4848 let items = driver.tag_items("user").unwrap();
4849 assert_eq!(items, vec!["user:1", "user:2", "user:3"]);
4850 }
4851
4852 #[test]
4853 fn test_tagset_clear_deletes_all_tagged_keys() {
4854 let cache = Cache::new();
4855 cache.register_default(MemoryCacheDriver::new());
4856
4857 cache.tag("user").set("user:1", "Alice", None).unwrap();
4858 cache.tag("user").set("user:2", "Bob", None).unwrap();
4859 cache.tag("user").set("user:3", "Carol", None).unwrap();
4860
4861 cache.tag("user").clear().unwrap();
4863
4864 assert!(cache.get::<String>("user:1").unwrap().is_none());
4865 assert!(cache.get::<String>("user:2").unwrap().is_none());
4866 assert!(cache.get::<String>("user:3").unwrap().is_none());
4867 }
4868
4869 #[test]
4870 fn test_tagset_clear_deletes_tag_key() {
4871 let cache = Cache::new();
4872 cache.register_default(MemoryCacheDriver::new());
4873
4874 cache.tag("user").set("user:1", "Alice", None).unwrap();
4875
4876 let mgr = cache.manager.read();
4878 let driver = mgr.default_store().unwrap();
4879 let tag_key = driver.get_tag_key("user");
4880 assert!(driver.has(&tag_key).unwrap());
4881 drop(mgr);
4882
4883 cache.tag("user").clear().unwrap();
4884
4885 let mgr = cache.manager.read();
4887 let driver = mgr.default_store().unwrap();
4888 assert!(!driver.has(&tag_key).unwrap());
4889 }
4890
4891 #[test]
4892 fn test_tagset_clear_empty_tag_no_error() {
4893 let cache = Cache::new();
4894 cache.register_default(MemoryCacheDriver::new());
4895
4896 cache.tag("empty").clear().unwrap();
4898 }
4899
4900 #[test]
4901 fn test_tagset_append_adds_key_to_tag() {
4902 let cache = Cache::new();
4903 cache.register_default(MemoryCacheDriver::new());
4904
4905 cache.set("user:1", "Alice", None).unwrap();
4907 cache.tag("user").append("user:1").unwrap();
4909
4910 let mgr = cache.manager.read();
4911 let driver = mgr.default_store().unwrap();
4912 let items = driver.tag_items("user").unwrap();
4913 assert_eq!(items, vec!["user:1"]);
4914 }
4915
4916 #[test]
4917 fn test_tagset_many_tags_single_key() {
4918 let cache = Cache::new();
4919 cache.register_default(MemoryCacheDriver::new());
4920
4921 cache
4923 .tag_many(&["user", "admin"])
4924 .set("key1", "val", None)
4925 .unwrap();
4926
4927 let mgr = cache.manager.read();
4929 let driver = mgr.default_store().unwrap();
4930 let user_items = driver.tag_items("user").unwrap();
4931 let admin_items = driver.tag_items("admin").unwrap();
4932 assert_eq!(user_items, vec!["key1"]);
4933 assert_eq!(admin_items, vec!["key1"]);
4934 }
4935
4936 #[test]
4937 fn test_tagset_many_tags_clear_one() {
4938 let cache = Cache::new();
4939 cache.register_default(MemoryCacheDriver::new());
4940
4941 cache
4942 .tag_many(&["user", "admin"])
4943 .set("key1", "val", None)
4944 .unwrap();
4945
4946 cache.tag("user").clear().unwrap();
4948
4949 assert!(cache.get::<String>("key1").unwrap().is_none());
4951
4952 let mgr = cache.manager.read();
4955 let driver = mgr.default_store().unwrap();
4956 let admin_items = driver.tag_items("admin").unwrap();
4957 assert_eq!(admin_items, vec!["key1"]); let user_tag_key = driver.get_tag_key("user");
4960 assert!(!driver.has(&user_tag_key).unwrap());
4961 }
4962
4963 #[test]
4964 fn test_tagset_tags_getter() {
4965 let cache = Cache::new();
4966 let ts = cache.tag_many(&["a", "b", "c"]);
4967 assert_eq!(ts.tags(), &["a", "b", "c"]);
4968 }
4969
4970 #[test]
4975 fn test_redis_tagset_set_stores_value_and_appends_tag() {
4976 let cache = Cache::new();
4977 let driver = RedisCacheDriver::new(RedisConfig::default());
4978 cache.register_store("redis", Box::new(driver));
4979
4980 cache.tag("user").set("user:1", "Alice", None).unwrap();
4981
4982 assert_eq!(
4984 cache.get::<String>("user:1").unwrap(),
4985 Some("Alice".to_string())
4986 );
4987
4988 let mgr = cache.manager.read();
4990 let driver = mgr.default_store().unwrap();
4991 let items = driver.tag_items("user").unwrap();
4992 assert_eq!(items, vec!["user:1"]);
4993 }
4994
4995 #[test]
4996 fn test_redis_tagset_set_with_prefix() {
4997 let cache = Cache::new();
4998 let config = RedisConfig {
4999 prefix: "app:".to_string(),
5000 ..RedisConfig::default()
5001 };
5002 let driver = RedisCacheDriver::new(config);
5003 cache.register_store("redis", Box::new(driver));
5004
5005 cache.tag("user").set("user:1", "Alice", None).unwrap();
5006
5007 let mgr = cache.manager.read();
5009 let driver = mgr.default_store().unwrap();
5010 let items = driver.tag_items("user").unwrap();
5011 assert_eq!(items, vec!["app:user:1"]);
5012 }
5013
5014 #[test]
5015 fn test_redis_tagset_clear_deletes_all_tagged_keys() {
5016 let cache = Cache::new();
5017 let driver = RedisCacheDriver::new(RedisConfig::default());
5018 cache.register_store("redis", Box::new(driver));
5019
5020 cache.tag("user").set("user:1", "Alice", None).unwrap();
5021 cache.tag("user").set("user:2", "Bob", None).unwrap();
5022 cache.tag("user").set("user:3", "Carol", None).unwrap();
5023
5024 cache.tag("user").clear().unwrap();
5025
5026 assert!(cache.get::<String>("user:1").unwrap().is_none());
5027 assert!(cache.get::<String>("user:2").unwrap().is_none());
5028 assert!(cache.get::<String>("user:3").unwrap().is_none());
5029 }
5030
5031 #[test]
5032 fn test_redis_tagset_clear_deletes_tag_key() {
5033 let cache = Cache::new();
5034 let driver = RedisCacheDriver::new(RedisConfig::default());
5035 cache.register_store("redis", Box::new(driver));
5036
5037 cache.tag("user").set("user:1", "Alice", None).unwrap();
5038
5039 let mgr = cache.manager.read();
5040 let driver = mgr.default_store().unwrap();
5041 let tag_key = driver.get_tag_key("user");
5042 assert!(driver.has(&tag_key).unwrap());
5044 drop(mgr);
5045
5046 cache.tag("user").clear().unwrap();
5047
5048 let mgr = cache.manager.read();
5049 let driver = mgr.default_store().unwrap();
5050 assert!(!driver.has(&tag_key).unwrap());
5051 }
5052
5053 #[test]
5054 fn test_redis_tagset_many_tags() {
5055 let cache = Cache::new();
5056 let driver = RedisCacheDriver::new(RedisConfig::default());
5057 cache.register_store("redis", Box::new(driver));
5058
5059 cache
5060 .tag_many(&["user", "admin"])
5061 .set("key1", "val", None)
5062 .unwrap();
5063
5064 let mgr = cache.manager.read();
5065 let driver = mgr.default_store().unwrap();
5066 let user_items = driver.tag_items("user").unwrap();
5067 let admin_items = driver.tag_items("admin").unwrap();
5068 assert_eq!(user_items, vec!["key1"]);
5069 assert_eq!(admin_items, vec!["key1"]);
5070 }
5071
5072 #[test]
5077 fn test_r5_php_tag_set_then_clear() {
5078 let cache = Cache::new();
5080 cache.register_default(MemoryCacheDriver::new());
5081
5082 cache.tag("user").set("u1", "Alice", None).unwrap();
5083 cache.tag("user").set("u2", "Bob", None).unwrap();
5084
5085 cache.set("other", "data", None).unwrap();
5087
5088 cache.tag("user").clear().unwrap();
5089
5090 assert!(cache.get::<String>("u1").unwrap().is_none());
5092 assert!(cache.get::<String>("u2").unwrap().is_none());
5093 assert_eq!(
5095 cache.get::<String>("other").unwrap(),
5096 Some("data".to_string())
5097 );
5098 }
5099
5100 #[test]
5101 fn test_r5_php_tag_multiple_tags_clear() {
5102 let cache = Cache::new();
5104 cache.register_default(MemoryCacheDriver::new());
5105
5106 cache
5108 .tag_many(&["user", "admin"])
5109 .set("key1", "v1", None)
5110 .unwrap();
5111 cache.tag("user").set("key2", "v2", None).unwrap();
5113
5114 cache.tag("user").clear().unwrap();
5116
5117 assert!(cache.get::<String>("key1").unwrap().is_none());
5118 assert!(cache.get::<String>("key2").unwrap().is_none());
5119 }
5120
5121 #[test]
5122 fn test_r5_php_tag_get_cache_key_prefix() {
5123 let cache = Cache::new();
5125 cache.register_default(MemoryCacheDriver::new());
5126 let mgr = cache.manager.read();
5127 let driver = mgr.default_store().unwrap();
5128 assert_eq!(driver.get_cache_key("test"), "test");
5129 }
5130
5131 #[test]
5132 fn test_r5_php_tag_get_tag_key_md5() {
5133 let cache = Cache::new();
5135 cache.register_default(MemoryCacheDriver::new());
5136 let mgr = cache.manager.read();
5137 let driver = mgr.default_store().unwrap();
5138 assert_eq!(
5140 driver.get_tag_key("hello"),
5141 "tag:5d41402abc4b2a76b9719d911017c592"
5142 );
5143 }
5144
5145 #[test]
5146 fn test_r5_php_tag_push_max_1000_array_shift() {
5147 let driver = MemoryCacheDriver::new();
5149 for i in 0..1005i64 {
5150 driver.tag_append("tag:test", &format!("key{}", i)).unwrap();
5151 }
5152 let storage_key = "tag:test";
5153 let raw = driver.get_raw(storage_key).unwrap();
5154 let stored: Vec<String> = serde_json::from_slice(&raw.unwrap()).unwrap();
5155 assert_eq!(stored.len(), 1000);
5157 assert!(!stored.contains(&"key0".to_string()));
5159 assert!(!stored.contains(&"key4".to_string()));
5160 assert!(stored.contains(&"key5".to_string()));
5162 assert!(stored.contains(&"key1004".to_string()));
5163 }
5164
5165 #[test]
5166 fn test_r5_php_tag_push_array_unique() {
5167 let driver = MemoryCacheDriver::new();
5169 driver.tag_append("tag:u", "a").unwrap();
5170 driver.tag_append("tag:u", "b").unwrap();
5171 driver.tag_append("tag:u", "a").unwrap(); driver.tag_append("tag:u", "c").unwrap();
5173 driver.tag_append("tag:u", "b").unwrap(); let storage_key = "tag:u";
5176 let raw = driver.get_raw(storage_key).unwrap();
5177 let stored: Vec<String> = serde_json::from_slice(&raw.unwrap()).unwrap();
5178 assert_eq!(stored, vec!["a", "b", "c"]);
5180 }
5181
5182 #[test]
5183 fn test_r5_php_tag_singleton_equivalent() {
5184 let cache = Cache::new();
5186 cache.register_default(MemoryCacheDriver::new());
5187
5188 cache.tag("user").set("u1", "Alice", None).unwrap();
5190 cache.tag("user").set("u2", "Bob", None).unwrap();
5192
5193 let mgr = cache.manager.read();
5195 let driver = mgr.default_store().unwrap();
5196 let items = driver.tag_items("user").unwrap();
5197 assert_eq!(items, vec!["u1", "u2"]);
5198
5199 cache.tag("user").clear().unwrap();
5201 assert!(cache.get::<String>("u1").unwrap().is_none());
5202 assert!(cache.get::<String>("u2").unwrap().is_none());
5203 }
5204
5205 #[test]
5206 fn test_r5_php_tag_clear_then_set_again() {
5207 let cache = Cache::new();
5209 cache.register_default(MemoryCacheDriver::new());
5210
5211 cache.tag("user").set("u1", "Alice", None).unwrap();
5212 cache.tag("user").clear().unwrap();
5213 assert!(cache.get::<String>("u1").unwrap().is_none());
5214
5215 cache.tag("user").set("u1", "Alice2", None).unwrap();
5217 assert_eq!(
5218 cache.get::<String>("u1").unwrap(),
5219 Some("Alice2".to_string())
5220 );
5221
5222 let mgr = cache.manager.read();
5224 let driver = mgr.default_store().unwrap();
5225 let items = driver.tag_items("user").unwrap();
5226 assert_eq!(items, vec!["u1"]);
5227 }
5228
5229 #[test]
5230 fn test_r5_php_tag_redis_set_then_clear() {
5231 let cache = Cache::new();
5233 let driver = RedisCacheDriver::new(RedisConfig::default());
5234 cache.register_store("redis", Box::new(driver));
5235
5236 cache.tag("article").set("a:1", "Hello", None).unwrap();
5237 cache.tag("article").set("a:2", "World", None).unwrap();
5238 cache.set("untagged", "data", None).unwrap();
5239
5240 cache.tag("article").clear().unwrap();
5241
5242 assert!(cache.get::<String>("a:1").unwrap().is_none());
5243 assert!(cache.get::<String>("a:2").unwrap().is_none());
5244 assert_eq!(
5246 cache.get::<String>("untagged").unwrap(),
5247 Some("data".to_string())
5248 );
5249 }
5250
5251 #[test]
5252 fn test_r5_php_tag_redis_with_prefix() {
5253 let cache = Cache::new();
5255 let config = RedisConfig {
5256 prefix: "myapp:".to_string(),
5257 tag_prefix: "tag:".to_string(),
5258 ..RedisConfig::default()
5259 };
5260 let driver = RedisCacheDriver::new(config);
5261 cache.register_store("redis", Box::new(driver));
5262
5263 cache.tag("user").set("u1", "Alice", None).unwrap();
5264
5265 let mgr = cache.manager.read();
5267 let driver = mgr.default_store().unwrap();
5268 let items = driver.tag_items("user").unwrap();
5269 assert_eq!(items, vec!["myapp:u1"]);
5270
5271 drop(mgr);
5273 cache.tag("user").clear().unwrap();
5274 assert!(cache.get::<String>("u1").unwrap().is_none());
5275 }
5276
5277 #[test]
5278 fn test_r5_php_tag_different_tags_isolation() {
5279 let cache = Cache::new();
5281 cache.register_default(MemoryCacheDriver::new());
5282
5283 cache.tag("user").set("u1", "Alice", None).unwrap();
5284 cache.tag("article").set("a1", "Hello", None).unwrap();
5285
5286 cache.tag("user").clear().unwrap();
5288
5289 assert!(cache.get::<String>("u1").unwrap().is_none());
5290 assert_eq!(
5291 cache.get::<String>("a1").unwrap(),
5292 Some("Hello".to_string())
5293 );
5294 }
5295
5296 #[test]
5297 fn test_r5_php_tag_set_with_ttl() {
5298 let cache = Cache::new();
5300 cache.register_default(MemoryCacheDriver::new());
5301
5302 cache
5303 .tag("user")
5304 .set("u1", "Alice", Some(Duration::from_millis(50)))
5305 .unwrap();
5306
5307 assert_eq!(
5308 cache.get::<String>("u1").unwrap(),
5309 Some("Alice".to_string())
5310 );
5311
5312 std::thread::sleep(Duration::from_millis(60));
5313 assert!(cache.get::<String>("u1").unwrap().is_none());
5314 }
5315
5316 #[test]
5321 fn test_delete_many_multiple_keys() {
5322 let cache = Cache::new();
5324 cache.register_default(MemoryCacheDriver::new());
5325 cache.set("k1", "v1", None).unwrap();
5326 cache.set("k2", "v2", None).unwrap();
5327 cache.set("k3", "v3", None).unwrap();
5328
5329 cache.delete_many(&["k1", "k2", "k3"]).unwrap();
5330
5331 assert!(cache.get::<String>("k1").unwrap().is_none());
5332 assert!(cache.get::<String>("k2").unwrap().is_none());
5333 assert!(cache.get::<String>("k3").unwrap().is_none());
5334 }
5335
5336 #[test]
5337 fn test_delete_many_nonexistent_keys_ok() {
5338 let cache = Cache::new();
5340 cache.register_default(MemoryCacheDriver::new());
5341 cache.set("exists", "v", None).unwrap();
5342
5343 let result = cache.delete_many(&["exists", "nonexistent"]);
5345 assert!(result.is_ok());
5346 }
5347
5348 #[test]
5349 fn test_delete_many_empty_slice() {
5350 let cache = Cache::new();
5352 cache.register_default(MemoryCacheDriver::new());
5353 let result = cache.delete_many(&[]);
5354 assert!(result.is_ok());
5355 }
5356
5357 #[test]
5358 fn test_delete_many_partial_delete_before_failure() {
5359 let cache = Cache::new();
5362 cache.register_default(MemoryCacheDriver::new());
5363 cache.set("a", "1", None).unwrap();
5364 cache.set("b", "2", None).unwrap();
5365
5366 cache.delete_many(&["a", "b"]).unwrap();
5367 assert!(cache.get::<String>("a").unwrap().is_none());
5368 assert!(cache.get::<String>("b").unwrap().is_none());
5369 }
5370
5371 #[test]
5376 fn test_invalidate_after_write_basic() {
5377 let cache = Cache::new();
5379 cache.register_default(MemoryCacheDriver::new());
5380 cache.set("user:1", "Alice", None).unwrap();
5381 assert_eq!(
5382 cache.get::<String>("user:1").unwrap(),
5383 Some("Alice".to_string())
5384 );
5385
5386 cache.invalidate_after_write(&["user:1"]).unwrap();
5388 assert!(cache.get::<String>("user:1").unwrap().is_none());
5389 }
5390
5391 #[test]
5392 fn test_invalidate_after_write_multiple_keys() {
5393 let cache = Cache::new();
5395 cache.register_default(MemoryCacheDriver::new());
5396 cache.set("sdp_category_tree", "t1", None).unwrap();
5397 cache.set("sdp_category_select", "s1", None).unwrap();
5398 cache.set("sdp_category_child", "c1", None).unwrap();
5399
5400 cache
5401 .invalidate_after_write(&[
5402 "sdp_category_tree",
5403 "sdp_category_select",
5404 "sdp_category_child",
5405 ])
5406 .unwrap();
5407
5408 assert!(cache.get::<String>("sdp_category_tree").unwrap().is_none());
5409 assert!(cache
5410 .get::<String>("sdp_category_select")
5411 .unwrap()
5412 .is_none());
5413 assert!(cache.get::<String>("sdp_category_child").unwrap().is_none());
5414 }
5415
5416 #[test]
5417 fn test_invalidate_after_write_fire_and_forget() {
5418 let cache = Cache::new();
5420 cache.register_default(MemoryCacheDriver::new());
5421 cache.set("clerk:1", "data", None).unwrap();
5422
5423 let _ = cache.invalidate_after_write(&["clerk:1"]);
5425 assert!(cache.get::<String>("clerk:1").unwrap().is_none());
5426 }
5427
5428 #[test]
5433 fn test_refresh_force_update() {
5434 let cache = Cache::new();
5436 cache.register_default(MemoryCacheDriver::new());
5437 cache.set("store:1", "old_data", None).unwrap();
5438
5439 let result: String = cache
5440 .refresh("store:1", None, || Ok("new_data".to_string()))
5441 .unwrap();
5442
5443 assert_eq!(result, "new_data");
5444 assert_eq!(
5445 cache.get::<String>("store:1").unwrap(),
5446 Some("new_data".to_string())
5447 );
5448 }
5449
5450 #[test]
5451 fn test_refresh_fetcher_error_no_write() {
5452 let cache = Cache::new();
5454 cache.register_default(MemoryCacheDriver::new());
5455 cache.set("key", "original", None).unwrap();
5456
5457 let result: Result<String, CacheError> = cache.refresh("key", None, || {
5459 Err(CacheError::SerializationError("fetch failed".to_string()))
5460 });
5461
5462 assert!(result.is_err());
5463 assert!(cache.get::<String>("key").unwrap().is_none());
5465 }
5466
5467 #[test]
5468 fn test_refresh_ttl_propagation() {
5469 let cache = Cache::new();
5471 cache.register_default(MemoryCacheDriver::new());
5472
5473 let _result: String = cache
5474 .refresh("ttl_key", Some(Duration::from_millis(50)), || {
5475 Ok("value".to_string())
5476 })
5477 .unwrap();
5478
5479 assert_eq!(
5481 cache.get::<String>("ttl_key").unwrap(),
5482 Some("value".to_string())
5483 );
5484
5485 std::thread::sleep(Duration::from_millis(60));
5487 assert!(cache.get::<String>("ttl_key").unwrap().is_none());
5488 }
5489
5490 #[test]
5491 fn test_refresh_returns_fetcher_value() {
5492 let cache = Cache::new();
5495 cache.register_default(MemoryCacheDriver::new());
5496 cache.set("counter", "old_value", None).unwrap();
5497
5498 let result: String = cache
5499 .refresh("counter", None, || Ok("new_value".to_string()))
5500 .unwrap();
5501 assert_eq!(result, "new_value");
5502 assert_eq!(
5503 cache.get::<String>("counter").unwrap(),
5504 Some("new_value".to_string())
5505 );
5506 }
5507
5508 #[test]
5513 fn test_r5_php_delete_multiple_semantics() {
5514 let cache = Cache::new();
5517 cache.register_default(MemoryCacheDriver::new());
5518 cache.set("a", "1", None).unwrap();
5519 cache.set("b", "2", None).unwrap();
5520 cache.set("c", "3", None).unwrap();
5521
5522 let result = cache.delete_many(&["a", "b", "c"]);
5524 assert!(result.is_ok()); assert!(cache.get::<String>("a").unwrap().is_none());
5528 assert!(cache.get::<String>("b").unwrap().is_none());
5529 assert!(cache.get::<String>("c").unwrap().is_none());
5530 }
5531
5532 #[test]
5533 fn test_r5_php_invalidate_after_write_pattern() {
5534 let cache = Cache::new();
5537 cache.register_default(MemoryCacheDriver::new());
5538
5539 cache
5541 .set("foodCashierClerkAll_1", vec!["clerk1"], None)
5542 .unwrap();
5543
5544 let write_success = true;
5546 if write_success {
5547 cache
5548 .invalidate_after_write(&["foodCashierClerkAll_1"])
5549 .unwrap();
5550 }
5551
5552 assert!(cache
5554 .get::<Vec<String>>("foodCashierClerkAll_1")
5555 .unwrap()
5556 .is_none());
5557 }
5558
5559 #[test]
5560 fn test_r5_php_refresh_pattern() {
5561 let cache = Cache::new();
5564 cache.register_default(MemoryCacheDriver::new());
5565
5566 cache
5568 .set("wmall_store_info_1", "old_store_data", None)
5569 .unwrap();
5570
5571 let result: String = cache
5573 .refresh("wmall_store_info_1", None, || {
5574 Ok("fresh_store_data".to_string())
5576 })
5577 .unwrap();
5578
5579 assert_eq!(result, "fresh_store_data");
5580 assert_eq!(
5581 cache.get::<String>("wmall_store_info_1").unwrap(),
5582 Some("fresh_store_data".to_string())
5583 );
5584 }
5585
5586 #[test]
5591 fn test_fetch_singleflight_cache_hit() {
5592 let cache = Cache::new();
5594 cache.register_default(MemoryCacheDriver::new());
5595 cache.set("hot", "cached_value", None).unwrap();
5596
5597 let called = Arc::new(Mutex::new(false));
5598 let called_clone = called.clone();
5599 let result: String = cache
5600 .fetch_singleflight("hot", None, || {
5601 *called_clone.lock() = true;
5602 Ok("fetcher_value".to_string())
5603 })
5604 .unwrap();
5605
5606 assert_eq!(result, "cached_value");
5607 assert!(!*called.lock(), "fetcher 不应被调用(缓存命中)");
5608 }
5609
5610 #[test]
5611 fn test_fetch_singleflight_cache_miss_invokes_fetcher() {
5612 let cache = Cache::new();
5614 cache.register_default(MemoryCacheDriver::new());
5615
5616 let result: String = cache
5617 .fetch_singleflight("miss_key", None, || Ok("fetched".to_string()))
5618 .unwrap();
5619
5620 assert_eq!(result, "fetched");
5621 assert_eq!(
5622 cache.get::<String>("miss_key").unwrap(),
5623 Some("fetched".to_string())
5624 );
5625 }
5626
5627 #[test]
5628 fn test_fetch_singleflight_concurrent_only_one_fetcher_call() {
5629 let cache = Arc::new(Cache::new());
5631 cache.register_default(MemoryCacheDriver::new());
5632
5633 let fetcher_call_count = Arc::new(Mutex::new(0u32));
5634 let barrier = Arc::new(Barrier::new(4));
5635 let results = Arc::new(Mutex::new(Vec::<String>::new()));
5636
5637 let mut handles = Vec::new();
5638 for _ in 0..4 {
5639 let cache_clone = Arc::clone(&cache);
5640 let count_clone = Arc::clone(&fetcher_call_count);
5641 let barrier_clone = Arc::clone(&barrier);
5642 let results_clone = Arc::clone(&results);
5643
5644 handles.push(std::thread::spawn(move || {
5645 barrier_clone.wait();
5647
5648 let value: String = cache_clone
5649 .fetch_singleflight("concurrent_key", None, || {
5650 std::thread::sleep(Duration::from_millis(50));
5652 let mut count = count_clone.lock();
5653 *count += 1;
5654 Ok(format!("fetched_{}", *count))
5655 })
5656 .unwrap();
5657
5658 results_clone.lock().push(value);
5659 }));
5660 }
5661
5662 for handle in handles {
5663 handle.join().unwrap();
5664 }
5665
5666 assert_eq!(
5668 *fetcher_call_count.lock(),
5669 1,
5670 "fetcher 应只调用一次(singleflight)"
5671 );
5672
5673 let results = results.lock();
5675 assert_eq!(results.len(), 4);
5676 for value in results.iter() {
5677 assert_eq!(value, "fetched_1");
5678 }
5679 }
5680
5681 #[test]
5682 fn test_fetch_singleflight_fetcher_error_propagates() {
5683 let cache = Cache::new();
5685 cache.register_default(MemoryCacheDriver::new());
5686
5687 let result: Result<String, CacheError> = cache.fetch_singleflight("err_key", None, || {
5688 Err(CacheError::SerializationError("fetcher failed".to_string()))
5689 });
5690
5691 assert!(result.is_err());
5692 assert!(cache.get::<String>("err_key").unwrap().is_none());
5693 }
5694
5695 #[test]
5700 fn test_set_with_jitter_basic() {
5701 let cache = Cache::new();
5703 cache.register_default(MemoryCacheDriver::new());
5704
5705 cache
5706 .set_with_jitter(
5707 "jitter_key",
5708 "value",
5709 Some(Duration::from_secs(60)),
5710 Duration::from_secs(10),
5711 )
5712 .unwrap();
5713
5714 assert_eq!(
5715 cache.get::<String>("jitter_key").unwrap(),
5716 Some("value".to_string())
5717 );
5718 }
5719
5720 #[test]
5721 fn test_set_with_jitter_zero_jitter_equivalent_to_set() {
5722 let cache = Cache::new();
5724 cache.register_default(MemoryCacheDriver::new());
5725
5726 cache
5727 .set_with_jitter(
5728 "no_jitter",
5729 "value",
5730 Some(Duration::from_secs(60)),
5731 Duration::ZERO,
5732 )
5733 .unwrap();
5734
5735 assert_eq!(
5736 cache.get::<String>("no_jitter").unwrap(),
5737 Some("value".to_string())
5738 );
5739 }
5740
5741 #[test]
5742 fn test_set_with_jitter_none_ttl_no_jitter() {
5743 let cache = Cache::new();
5745 cache.register_default(MemoryCacheDriver::new());
5746
5747 cache
5748 .set_with_jitter("permanent", "value", None, Duration::from_secs(10))
5749 .unwrap();
5750
5751 assert_eq!(
5752 cache.get::<String>("permanent").unwrap(),
5753 Some("value".to_string())
5754 );
5755 }
5756
5757 #[test]
5758 fn test_set_with_jitter_ttl_in_expected_range() {
5759 let cache = Cache::new();
5761 cache.register_default(MemoryCacheDriver::new());
5762
5763 let base_ttl = Duration::from_millis(50);
5764 let jitter = Duration::from_millis(100);
5765
5766 cache
5767 .set_with_jitter("range_key", "value", Some(base_ttl), jitter)
5768 .unwrap();
5769
5770 assert!(cache.get::<String>("range_key").unwrap().is_some());
5772
5773 std::thread::sleep(base_ttl + jitter + Duration::from_millis(20));
5775 assert!(
5776 cache.get::<String>("range_key").unwrap().is_none(),
5777 "TTL 应在 [{:?}, {:?}] 范围内,已过期",
5778 base_ttl,
5779 base_ttl + jitter
5780 );
5781 }
5782
5783 #[test]
5788 fn test_fetch_with_protection_cache_hit() {
5789 let cache = Cache::new();
5791 cache.register_default(MemoryCacheDriver::new());
5792 cache.set("protected", "cached", None).unwrap();
5793
5794 let called = Arc::new(Mutex::new(false));
5795 let called_clone = called.clone();
5796 let result: String = cache
5797 .fetch_with_protection(
5798 "protected",
5799 Some(Duration::from_secs(60)),
5800 Duration::from_secs(10),
5801 || {
5802 *called_clone.lock() = true;
5803 Ok("fetched".to_string())
5804 },
5805 )
5806 .unwrap();
5807
5808 assert_eq!(result, "cached");
5809 assert!(!*called.lock());
5810 }
5811
5812 #[test]
5813 fn test_fetch_with_protection_cache_miss_invokes_fetcher() {
5814 let cache = Cache::new();
5816 cache.register_default(MemoryCacheDriver::new());
5817
5818 let result: String = cache
5819 .fetch_with_protection(
5820 "miss_protected",
5821 Some(Duration::from_secs(60)),
5822 Duration::from_secs(10),
5823 || Ok("fetched_protected".to_string()),
5824 )
5825 .unwrap();
5826
5827 assert_eq!(result, "fetched_protected");
5828 assert_eq!(
5829 cache.get::<String>("miss_protected").unwrap(),
5830 Some("fetched_protected".to_string())
5831 );
5832 }
5833
5834 #[test]
5835 fn test_fetch_with_protection_concurrent_single_flight() {
5836 let cache = Arc::new(Cache::new());
5838 cache.register_default(MemoryCacheDriver::new());
5839
5840 let fetcher_call_count = Arc::new(Mutex::new(0u32));
5841 let barrier = Arc::new(Barrier::new(4));
5842 let results = Arc::new(Mutex::new(Vec::<String>::new()));
5843
5844 let mut handles = Vec::new();
5845 for _ in 0..4 {
5846 let cache_clone = Arc::clone(&cache);
5847 let count_clone = Arc::clone(&fetcher_call_count);
5848 let barrier_clone = Arc::clone(&barrier);
5849 let results_clone = Arc::clone(&results);
5850
5851 handles.push(std::thread::spawn(move || {
5852 barrier_clone.wait();
5853
5854 let value: String = cache_clone
5855 .fetch_with_protection(
5856 "concurrent_protected",
5857 Some(Duration::from_secs(60)),
5858 Duration::from_secs(10),
5859 || {
5860 std::thread::sleep(Duration::from_millis(50));
5861 let mut count = count_clone.lock();
5862 *count += 1;
5863 Ok(format!("value_{}", *count))
5864 },
5865 )
5866 .unwrap();
5867
5868 results_clone.lock().push(value);
5869 }));
5870 }
5871
5872 for handle in handles {
5873 handle.join().unwrap();
5874 }
5875
5876 assert_eq!(*fetcher_call_count.lock(), 1, "fetcher 应只调用一次");
5877
5878 let results = results.lock();
5879 assert_eq!(results.len(), 4);
5880 for value in results.iter() {
5881 assert_eq!(value, "value_1");
5882 }
5883 }
5884
5885 #[test]
5886 fn test_fetch_with_protection_fetcher_error_propagates() {
5887 let cache = Cache::new();
5889 cache.register_default(MemoryCacheDriver::new());
5890
5891 let result: Result<String, CacheError> = cache.fetch_with_protection(
5892 "err_protected",
5893 Some(Duration::from_secs(60)),
5894 Duration::from_secs(10),
5895 || Err(CacheError::SerializationError("failed".to_string())),
5896 );
5897
5898 assert!(result.is_err());
5899 assert!(cache.get::<String>("err_protected").unwrap().is_none());
5900 }
5901
5902 #[test]
5907 fn test_r5_php_remember_lock_vs_rust_singleflight() {
5908 let cache = Arc::new(Cache::new());
5912 cache.register_default(MemoryCacheDriver::new());
5913
5914 let call_count = Arc::new(Mutex::new(0u32));
5915 let barrier = Arc::new(Barrier::new(3));
5916 let results = Arc::new(Mutex::new(Vec::<String>::new()));
5917
5918 let mut handles = Vec::new();
5919 for _ in 0..3 {
5920 let cache_clone = Arc::clone(&cache);
5921 let count_clone = Arc::clone(&call_count);
5922 let barrier_clone = Arc::clone(&barrier);
5923 let results_clone = Arc::clone(&results);
5924
5925 handles.push(std::thread::spawn(move || {
5926 barrier_clone.wait();
5927
5928 let value: String = cache_clone
5929 .fetch_singleflight("r5_compare_key", None, || {
5930 std::thread::sleep(Duration::from_millis(30));
5931 let mut count = count_clone.lock();
5932 *count += 1;
5933 Ok(format!("v_{}", *count))
5934 })
5935 .unwrap();
5936
5937 results_clone.lock().push(value);
5938 }));
5939 }
5940
5941 for handle in handles {
5942 handle.join().unwrap();
5943 }
5944
5945 assert_eq!(
5947 *call_count.lock(),
5948 1,
5949 "Rust singleflight fetcher 应只调用一次"
5950 );
5951
5952 let results = results.lock();
5954 assert_eq!(results.len(), 3);
5955 for value in results.iter() {
5956 assert_eq!(value, "v_1");
5957 }
5958 }
5959
5960 #[test]
5961 fn test_r5_php_no_jitter_vs_rust_jitter() {
5962 let cache = Cache::new();
5966 cache.register_default(MemoryCacheDriver::new());
5967
5968 let mut ttl_samples = Vec::new();
5970 for i in 0..10 {
5971 let key = format!("jitter_sample_{}", i);
5972 cache
5973 .set_with_jitter(
5974 &key,
5975 "value",
5976 Some(Duration::from_secs(60)),
5977 Duration::from_secs(10),
5978 )
5979 .unwrap();
5980
5981 let _ = cache.get::<String>(&key).unwrap();
5984 ttl_samples.push(key);
5985 }
5986
5987 for key in &ttl_samples {
5989 assert_eq!(
5990 cache.get::<String>(key).unwrap(),
5991 Some("value".to_string()),
5992 "所有带抖动 TTL 的 key 都应写入成功"
5993 );
5994 }
5995 }
5996
5997 #[test]
5998 fn test_r5_php_remember_no_double_check_vs_rust_double_check() {
5999 let cache = Cache::new();
6003 cache.register_default(MemoryCacheDriver::new());
6004
6005 cache.set("double_check_key", "pre_cached", None).unwrap();
6007
6008 let called = Arc::new(Mutex::new(false));
6010 let called_clone = called.clone();
6011 let result: String = cache
6012 .fetch_singleflight("double_check_key", None, || {
6013 *called_clone.lock() = true;
6014 Ok("fetched".to_string())
6015 })
6016 .unwrap();
6017
6018 assert_eq!(result, "pre_cached");
6020 assert!(
6021 !*called.lock(),
6022 "double-check 应命中预缓存,fetcher 不被调用"
6023 );
6024 }
6025}