use std::time::Duration;
use redis::AsyncCommands;
use serde::{Deserialize, Serialize};
use crate::cache::{HttpCacheKey, HttpCacheStorage};
pub struct HttpCacheRedis {
cache_ttl: Duration,
prefix: Option<Vec<u8>>,
client: redis::Client,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct Config {
pub key_prefix: Option<String>,
pub connection_string: String,
}
impl HttpCacheRedis {
pub fn new(client: redis::Client) -> Self {
Self {
client,
prefix: None,
cache_ttl: Duration::from_secs(60),
}
}
pub fn set_prefix(mut self, prefix: Vec<u8>) -> Self {
self.prefix = Some(prefix);
self
}
}
#[async_trait::async_trait]
impl HttpCacheStorage for HttpCacheRedis {
fn set_expiration_times(&mut self, cache_ttl: Duration, _cache_tti: Duration) {
self.cache_ttl = cache_ttl;
}
async fn get(&self, key: &HttpCacheKey) -> Option<Vec<u8>> {
let mut conn = self
.client
.get_multiplexed_tokio_connection()
.await
.map_err(|err| {
tracing::error!("Failed to get redis connection: {:?}", err);
err
})
.ok()?;
let mut db_key = self.prefix.clone().unwrap_or_default();
db_key.extend(&**key);
conn.get(db_key)
.await
.map_err(|err| {
tracing::error!("Failed to get value from redis: {:?}", err);
err
})
.ok()?
}
async fn set(&self, key: HttpCacheKey, value: Vec<u8>) {
let mut db_key = self.prefix.clone().unwrap_or_default();
db_key.extend(&*key);
let mut conn = match self.client.get_multiplexed_tokio_connection().await {
Ok(conn) => conn,
Err(err) => {
tracing::error!("Failed to get redis connection: {:?}", err);
return;
}
};
let _: Result<(), _> = conn
.set_ex(db_key, value, self.cache_ttl.as_secs() as usize)
.await
.map_err(|err| {
tracing::error!("Failed to set value in redis: {:?}", err);
err
});
}
}