use std::fmt::Display;
use crate::common::connection::{WriteMessageError, Writer};
use crate::common::message::ServerMessage;
use crate::common::message::{RoomId, RoomState};
use super::types::{ArcMut, Connections, RoomData};
#[derive(thiserror::Error, Debug)]
pub enum SendRoomUpdateError {
#[error("{}", .0)]
WriteMessageError(#[from] WriteMessageError),
#[error("{}", .0)]
Other(String),
}
impl From<String> for SendRoomUpdateError {
fn from(value: String) -> Self {
SendRoomUpdateError::Other(value)
}
}
pub async fn send_room_update<P: Display + std::hash::Hash + Clone + Eq, W: Writer>(
room_id: RoomId,
room: &ArcMut<RoomData<P>>,
streams: &Connections<P, W>,
) -> Result<(), SendRoomUpdateError> {
let room = room.lock().await;
let new_state = RoomState {
id: room_id,
users: {
let mut users: Box<[_]> = room.users.values().copied().collect();
users.sort_by_key(|u| u.id);
users
},
round: room.round.clone(),
};
let users = room.users.clone();
drop(room);
for (peer, user) in users {
let mut guard = streams.lock().await;
let stream = if let Some(stream) = guard.get_mut(&peer) {
stream
} else {
continue;
};
log::info!(
"Calling room_update for {peer} ({}) in room {room_id}",
user.id
);
stream
.write_message(ServerMessage::RoomUpdate {
new_state: new_state.clone(),
})
.await?;
}
Ok(())
}