use redis::Commands; use serde::{Serialize, de::DeserializeOwned}; use super::{Cache, EXPIRE_AT, TimedObject}; pub const EPOCH_YEAR: u32 = 2025; #[derive(Clone)] pub struct RedisCache { pub client: redis::Client, } impl Cache for RedisCache { type Item = String; type Client = redis::Connection; async fn new() -> Self { Self { client: redis::Client::open("redis://127.0.0.1:6379").unwrap(), } } async fn get_con(&self) -> Self::Client { self.client.get_connection().unwrap() } async fn get(&self, id: Self::Item) -> Option { self.get_con().await.get(id).ok() } async fn set(&self, id: Self::Item, content: Self::Item) -> bool { let mut c = self.get_con().await; let res: Result = c.set(id, content); res.is_ok() } async fn update(&self, id: Self::Item, content: Self::Item) -> bool { self.set(id, content).await } async fn remove(&self, id: Self::Item) -> bool { let mut c = self.get_con().await; let res: Result = c.del(id); res.is_ok() } async fn remove_starting_with(&self, id: Self::Item) -> bool { let mut c = self.get_con().await; // get keys let mut cmd = redis::cmd("DEL"); let keys: Result, redis::RedisError> = c.keys(id); for key in keys.unwrap() { cmd.arg(key); } // remove let res: Result = cmd.query(&mut c); res.is_ok() } async fn incr(&self, id: Self::Item) -> bool { let mut c = self.get_con().await; let res: Result = c.incr(id, 1); res.is_ok() } async fn decr(&self, id: Self::Item) -> bool { let mut c = self.get_con().await; let res: Result = c.decr(id, 1); res.is_ok() } async fn get_timed( &self, id: Self::Item, ) -> Option> { let mut c = self.get_con().await; let res: Result = c.get(&id); match res { Ok(d) => match serde_json::from_str::>(&d) { Ok(d) => { // check time let now = tetratto_shared::epoch_timestamp(EPOCH_YEAR); if now - d.0 >= EXPIRE_AT { // expired key, remove and return None self.remove(id).await; return None; } // return Some(d) } Err(_) => None, }, Err(_) => None, } } async fn set_timed(&self, id: Self::Item, content: T) -> bool { let mut c = self.get_con().await; let res: Result = c.set( id, match serde_json::to_string::>(&( tetratto_shared::epoch_timestamp(EPOCH_YEAR), content, )) { Ok(s) => s, Err(_) => return false, }, ); res.is_ok() } }