use redis::AsyncCommands; use std::time::Duration; use uuid::Uuid; #[derive(Clone)] pub struct DeduplicationManager { cache: db::cache::AppCache, window: Duration, } impl DeduplicationManager { pub fn new(cache: db::cache::AppCache) -> Self { Self { cache, window: Duration::from_secs(300), } } pub async fn check_and_mark( &self, message_id: Uuid, room_id: Uuid, ) -> Result { let key = format!("dedup:{}:{}", room_id, message_id); let mut conn = self.cache.conn().await .map_err(|_| crate::error::AppTransportError::Internal)?; let exists: bool = conn.exists(&key).await .map_err(|_| crate::error::AppTransportError::Internal)?; if exists { return Ok(false); } let _: () = conn.set_ex(&key, "1", self.window.as_secs()) .await .map_err(|_| crate::error::AppTransportError::Internal)?; Ok(true) } pub async fn is_duplicate( &self, message_id: Uuid, room_id: Uuid, ) -> Result { let key = format!("dedup:{}:{}", room_id, message_id); let mut conn = self.cache.conn().await .map_err(|_| crate::error::AppTransportError::Internal)?; let exists: bool = conn.exists(&key).await .map_err(|_| crate::error::AppTransportError::Internal)?; Ok(exists) } pub async fn cleanup_expired(&self) -> Result<(), crate::error::AppTransportError> { Ok(()) } }