70 lines
2.4 KiB
Rust
70 lines
2.4 KiB
Rust
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<broadcast::Receiver<Arc<RoomMessageEvent>>, 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);
|
|
}
|
|
}
|
|
}
|
|
}
|