use async_trait::async_trait;
use crate::CacheError;
use crate::redis_cache::{map_err, set_cmd};
#[async_trait]
pub(crate) trait HaCacheBackend: Send + Sync {
type Conn: redis::aio::ConnectionLike + Send;
async fn checkout(&self) -> Result<Self::Conn, CacheError>;
fn status(&self) -> deadpool_redis::Status;
async fn get(&self, key: &str) -> Result<Option<Vec<u8>>, CacheError> {
let mut conn = self.checkout().await?;
redis::cmd("GET").arg(key).query_async::<Option<Vec<u8>>>(&mut conn).await.map_err(map_err)
}
async fn delete_count(&self, key: &str) -> Result<i64, CacheError> {
let mut conn = self.checkout().await?;
redis::cmd("DEL").arg(key).query_async(&mut conn).await.map_err(map_err)
}
async fn set(&self, key: &str, value: Vec<u8>, ttl: Option<u64>) -> Result<(), CacheError> {
if ttl == Some(0) {
self.delete_count(key).await?;
return Ok(());
}
let mut conn = self.checkout().await?;
set_cmd(key, &value, ttl).query_async(&mut conn).await.map_err(map_err)
}
async fn delete(&self, key: &str) -> Result<(), CacheError> {
match self.delete_count(key).await? {
0 => Err(CacheError::NotFound),
_ => Ok(()),
}
}
async fn incr(&self, key: &str) -> Result<i64, CacheError> {
let mut conn = self.checkout().await?;
redis::cmd("INCR").arg(key).query_async(&mut conn).await.map_err(map_err)
}
}
macro_rules! impl_cache_for_ha {
($ty:ty) => {
#[async_trait::async_trait]
impl $crate::Cache for $ty {
async fn get(&self, key: &str) -> Result<Option<Vec<u8>>, $crate::CacheError> {
self.backend.get(key).await
}
async fn set(
&self,
key: &str,
value: Vec<u8>,
ttl: Option<u64>,
) -> Result<(), $crate::CacheError> {
self.backend.set(key, value, ttl).await
}
async fn delete(&self, key: &str) -> Result<(), $crate::CacheError> {
self.backend.delete(key).await
}
async fn incr(&self, key: &str) -> Result<i64, $crate::CacheError> {
self.backend.incr(key).await
}
}
};
}
pub(crate) use impl_cache_for_ha;