b453d5d
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<V>(&self, key: &str) -> Result<Option<V>, 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<V>(
&self,
key: &str,
value: &V,
ttl: Option<Duration>,
) -> 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<bool, CacheError> {
Ok(export::redis::exists(&self.redis, key).await?)
}
pub async fn get_bytes(&self, key: &str) -> Result<Option<Vec<u8>>, 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<u8>,
ttl: Option<Duration>,
) -> 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(())
}
}