- Add gitignore and prettier configuration files for project scaffolding - Implement room access control service with project member verification - Create user access key management with CRUD operations and activity logging - Add accordion UI component for frontend expandable sections - Implement room AI configuration with list, upsert, and delete operations - Add AI event types for agent join/leave/status change tracking - Create streaming AI processing services for mode and react patterns - Build room AI service with model detection and idempotency handling - Integrate chat service orchestration for AI message processing - Add typing indicators and stream cancellation for AI interactions - Implement mention parsing and context extraction for AI agents
63 lines
1.6 KiB
Rust
63 lines
1.6 KiB
Rust
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<bool, crate::error::AppTransportError> {
|
|
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<bool, crate::error::AppTransportError> {
|
|
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(())
|
|
}
|
|
}
|