use uuid::Uuid; use crate::cache::redis::AppRedis; use crate::error::AppResult; use ::redis::Cmd; use super::redis_keys::*; pub struct DedupManager { redis: AppRedis, window_secs: u64, } impl DedupManager { pub fn new(redis: AppRedis) -> Self { Self { redis, window_secs: WS_DEDUP_WINDOW_SECS, } } pub fn check_and_mark(&self, message_id: Uuid, channel_id: Uuid) -> AppResult { let key = format!("{WS_DEDUP_PREFIX}{channel_id}:{message_id}"); let mut conn = self.redis.get_connection()?; let result: Option = Cmd::new() .arg("SET") .arg(&key) .arg("1") .arg("NX") .arg("EX") .arg(self.window_secs) .query(&mut *conn.inner_mut()) .map_err(crate::error::AppError::Redis)?; Ok(result.is_some()) } pub fn is_duplicate(&self, message_id: Uuid, channel_id: Uuid) -> AppResult { let key = format!("{WS_DEDUP_PREFIX}{channel_id}:{message_id}"); let mut conn = self.redis.get_connection()?; let exists: bool = Cmd::new() .arg("EXISTS") .arg(&key) .query(&mut *conn.inner_mut()) .map_err(crate::error::AppError::Redis)?; Ok(exists) } pub fn clear(&self, message_id: Uuid, channel_id: Uuid) -> AppResult<()> { let key = format!("{WS_DEDUP_PREFIX}{channel_id}:{message_id}"); let mut conn = self.redis.get_connection()?; Cmd::new() .arg("DEL") .arg(&key) .query::<()>(&mut *conn.inner_mut()) .map_err(crate::error::AppError::Redis)?; Ok(()) } }