use std::sync::Arc; use uuid::Uuid; use tokio::sync::broadcast; use crate::error::RoomError; use super::{RoomConnectionManager, RoomMessageEvent, BROADCAST_CAPACITY, MAX_CONNECTIONS_PER_ROOM}; impl RoomConnectionManager { pub async fn subscribe(&self, room_id: Uuid, _user_id: Uuid) -> Result>, RoomError> { let mut map = self.room_inner.write().await; if let Some(_sender) = map.get(&room_id) { drop(map); let mut counts = self.room_subscriber_count.write().await; *counts.entry(room_id).or_insert(0) += 1; let map = self.room_inner.read().await; if let Some(sender) = map.get(&room_id) { return Ok(sender.subscribe()); } return Err(RoomError::Internal("room disappeared during subscribe".into())); } if map.len() >= MAX_CONNECTIONS_PER_ROOM { return Err(RoomError::RateLimited(format!( "Room connection limit reached ({})", MAX_CONNECTIONS_PER_ROOM ))); } let (tx, rx) = broadcast::channel(BROADCAST_CAPACITY); map.insert(room_id, tx); drop(map); let mut counts = self.room_subscriber_count.write().await; counts.insert(room_id, 1); self.metrics.users_online.increment(1.0); Ok(rx) } pub async fn unsubscribe(&self, room_id: Uuid, _user_id: Uuid) { let mut counts = self.room_subscriber_count.write().await; let count = counts.entry(room_id).or_insert(0); if *count > 0 { *count -= 1; self.metrics.users_online.decrement(1.0); } if *count == 0 { counts.remove(&room_id); drop(counts); let mut map = self.room_inner.write().await; map.remove(&room_id); } } pub async fn broadcast(&self, room_id: Uuid, event: RoomMessageEvent) { { let mut activity = self.room_last_activity.write().await; activity.insert(room_id, std::time::Instant::now()); } let map = self.room_inner.read().await; if let Some(sender) = map.get(&room_id) { let event = Arc::new(event); if sender.send(event).is_err() { self.metrics.broadcasts_dropped.increment(1); } else { self.metrics.broadcasts_sent.increment(1); } } } }