use std::time::Duration; use export::{AppRedis, RedisConnection}; use serde::Serialize; use serde::de::DeserializeOwned; use crate::error::CacheError; #[derive(Clone)] pub struct CacheClient { redis: AppRedis, } impl CacheClient { pub fn new(redis: AppRedis) -> Self { Self { redis } } pub fn raw(&self) -> &AppRedis { &self.redis } pub async fn get(&self, key: &str) -> Result, CacheError> where V: DeserializeOwned, { self.get_bytes(key) .await? .map(|bytes| serde_json::from_slice(&bytes).map_err(CacheError::from)) .transpose() } pub async fn set( &self, key: &str, value: &V, ttl: Option, ) -> Result<(), CacheError> where V: Serialize, { self.set_bytes(key, serde_json::to_vec(value)?, ttl).await } pub async fn delete(&self, key: &str) -> Result<(), CacheError> { Ok(export::redis::delete(&self.redis, key).await?) } pub async fn exists(&self, key: &str) -> Result { Ok(export::redis::exists(&self.redis, key).await?) } pub async fn get_bytes(&self, key: &str) -> Result>, CacheError> { let mut conn = self.redis.connection_clone(); let mut cmd = redis::cmd("GET"); cmd.arg(key); let value = match &mut conn { RedisConnection::Standalone(conn) => cmd.query_async(conn).await?, RedisConnection::Cluster(conn) => cmd.query_async(conn).await?, }; Ok(value) } pub async fn set_bytes( &self, key: &str, value: Vec, ttl: Option, ) -> Result<(), CacheError> { if ttl.is_some_and(|ttl| ttl.is_zero()) { return self.delete(key).await; } let mut cmd = redis::cmd("SET"); cmd.arg(key).arg(value); if let Some(ttl) = ttl { let millis = ttl.as_millis().max(1).min(u64::MAX as u128) as u64; cmd.arg("PX").arg(millis); } let mut conn = self.redis.connection_clone(); match &mut conn { RedisConnection::Standalone(conn) => cmd.exec_async(conn).await?, RedisConnection::Cluster(conn) => cmd.exec_async(conn).await?, } Ok(()) } }