diff --git a/src/lib.rs b/src/lib.rs index fa49324..443145e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -410,6 +410,13 @@ pub trait IOCached { /// Should return `Self::Error` if the operation fails fn cache_remove(&self, k: &K) -> Result, Self::Error>; + /// Remove all cached values + /// + /// # Errors + /// + /// Should return `Self::Error` if the operation fails + fn cache_clear(&self) -> Result<(), Self::Error>; + /// Set the flag to control whether cache hits refresh the ttl of cached values, returns the old flag value fn cache_set_refresh(&mut self, refresh: bool) -> bool; @@ -436,6 +443,9 @@ pub trait IOCachedAsync { /// Remove a cached value async fn cache_remove(&self, k: &K) -> Result, Self::Error>; + /// Remove all cached values + async fn cache_clear(&self) -> Result<(), Self::Error>; + /// Set the flag to control whether cache hits refresh the ttl of cached values, returns the old flag value fn cache_set_refresh(&mut self, refresh: bool) -> bool; diff --git a/src/stores/disk.rs b/src/stores/disk.rs index 33a85e7..7e41b49 100644 --- a/src/stores/disk.rs +++ b/src/stores/disk.rs @@ -269,6 +269,13 @@ where } } + fn cache_clear(&self) -> Result<(), Self::Error> { + for (key, value) in self.connection.iter().flatten() { + self.connection.remove(key)?; + } + Ok(()) + } + fn cache_lifespan(&self) -> Option { self.seconds } diff --git a/src/stores/redis.rs b/src/stores/redis.rs index 8e95dc7..010892f 100644 --- a/src/stores/redis.rs +++ b/src/stores/redis.rs @@ -1,4 +1,5 @@ use crate::IOCached; +use redis::Commands; use serde::de::DeserializeOwned; use serde::Serialize; use std::fmt::Display; @@ -217,7 +218,7 @@ where RedisCacheBuilder::new(prefix, seconds) } - fn generate_key(&self, key: &K) -> String { + fn generate_key(&self, key: impl Display) -> String { format!("{}{}{}", self.namespace, self.prefix, key) } @@ -341,6 +342,19 @@ where } } + fn cache_clear(&self) -> Result<(), Self::Error> { + // `scan_match` takes `&mut self`, so we need two connection objects to scan and + // delete...? + let mut scan = self.pool.get()?; + let mut delete = self.pool.get()?; + + for key in scan.scan_match::<_, String>(self.generate_key("*"))? { + delete.del(key)?; + } + + Ok(()) + } + fn cache_lifespan(&self) -> Option { Some(self.seconds) } @@ -626,6 +640,15 @@ mod async_redis { } } + async fn cache_clear(&self) -> Result<(), Self::Error> { + let mut conn = self.connection.clone(); + + // https://redis.io/commands/flushdb/ + let _: () = redis::cmd("FLUSHDB").query_async(&mut conn).await?; + + Ok(()) + } + /// Set the flag to control whether cache hits refresh the ttl of cached values, returns the old flag value fn cache_set_refresh(&mut self, refresh: bool) -> bool { let old = self.refresh;