use std::sync::Arc; use uuid::Uuid; use tokio::sync::broadcast; use crate::error::RoomError; use crate::types::NotificationEvent; use super::{RoomConnectionManager, ProjectRoomEvent, BROADCAST_CAPACITY, MAX_CONNECTIONS_PER_USER}; impl RoomConnectionManager { pub async fn subscribe_user(&self, user_id: Uuid) -> Result>, RoomError> { let mut map = self.user_inner.write().await; if let Some(_sender) = map.get(&user_id) { drop(map); let mut counts = self.user_subscriber_count.write().await; *counts.entry(user_id).or_insert(0) += 1; let map = self.user_inner.read().await; if let Some(sender) = map.get(&user_id) { return Ok(sender.subscribe()); } return Err(RoomError::Internal("user channel disappeared".into())); } if map.len() >= MAX_CONNECTIONS_PER_USER { return Err(RoomError::RateLimited(format!( "User connection limit reached ({})", MAX_CONNECTIONS_PER_USER ))); } let (tx, rx) = broadcast::channel(BROADCAST_CAPACITY); map.insert(user_id, tx); drop(map); let mut counts = self.user_subscriber_count.write().await; counts.insert(user_id, 1); self.metrics.users_online.increment(1.0); Ok(rx) } pub async fn unsubscribe_user(&self, user_id: Uuid) { let mut counts = self.user_subscriber_count.write().await; let count = counts.entry(user_id).or_insert(0); if *count > 0 { *count -= 1; } if *count == 0 { self.metrics.users_online.decrement(1.0); counts.remove(&user_id); drop(counts); let mut map = self.user_inner.write().await; map.remove(&user_id); } } pub async fn broadcast_to_user(&self, user_id: Uuid, event: ProjectRoomEvent) { let map = self.user_inner.read().await; if let Some(sender) = map.get(&user_id) { let event = Arc::new(event); if sender.send(event).is_err() { self.metrics.broadcasts_dropped.increment(1); } } } pub async fn subscribe_user_notification(&self, user_id: Uuid) -> broadcast::Receiver> { let mut map = self.user_notification_inner.write().await; if let Some(sender) = map.get(&user_id) { return sender.subscribe(); } let (tx, rx) = broadcast::channel(BROADCAST_CAPACITY); map.insert(user_id, tx); rx } pub async fn unsubscribe_user_notification(&self, user_id: Uuid) { let mut map = self.user_notification_inner.write().await; map.remove(&user_id); } pub async fn push_user_notification(&self, user_id: Uuid, event: Arc) { let map = self.user_notification_inner.read().await; if let Some(sender) = map.get(&user_id) { let _ = sender.send(event); } } }