use std::time::Duration;
use crate::cache::{CacheKey, CacheResult, CacheStore, MemoryCacheStore};
use async_trait::async_trait;
use crate::cache_redis::RedisCacheConfig;
#[derive(Debug, Clone)]
pub struct RedisCacheStore {
config: RedisCacheConfig,
delegate: MemoryCacheStore,
}
impl RedisCacheStore {
pub fn new(config: RedisCacheConfig) -> Self {
Self {
config,
delegate: MemoryCacheStore::new(),
}
}
pub fn namespace(&self) -> &str {
&self.config.namespace
}
pub async fn health_check(&self) -> CacheResult<()> {
let key = CacheKey::new(&self.config.namespace, ["health"]);
self.delegate
.set_raw(&key, b"ok".to_vec(), Some(self.config.default_ttl))
.await
}
}
#[async_trait]
impl CacheStore for RedisCacheStore {
async fn get_raw(&self, key: &CacheKey) -> CacheResult<Option<Vec<u8>>> {
self.delegate.get_raw(key).await
}
async fn set_raw(
&self,
key: &CacheKey,
value: Vec<u8>,
ttl: Option<Duration>,
) -> CacheResult<()> {
self.delegate
.set_raw(key, value, ttl.or(Some(self.config.default_ttl)))
.await
}
async fn delete(&self, key: &CacheKey) -> CacheResult<()> {
self.delegate.delete(key).await
}
}
#[cfg(test)]
mod tests {
use crate::cache::{CacheKey, CacheStore};
use crate::cache_redis::{RedisCacheConfig, RedisCacheStore};
#[tokio::test]
async fn redis_store_facade_supports_cache_trait() {
let store = RedisCacheStore::new(RedisCacheConfig::default());
let key = CacheKey::new(store.namespace(), ["user", "1"]);
store
.set_json(&key, &serde_json::json!({"id":1}), None)
.await
.expect("set");
let value: serde_json::Value = store.get_json(&key).await.expect("get").expect("value");
assert_eq!(value["id"], 1);
store.health_check().await.expect("health");
}
}