use std::collections::HashMap; use axum::extract::ws::WebSocket; use tokio::sync::mpsc; use tokio::sync::oneshot; use super::room; pub enum RoomServiceRequest { Exists(String, oneshot::Sender), Join(String, WebSocket), Remove(String), } pub type RoomService = mpsc::Sender; type RoomMap = HashMap; async fn handle_room_server_message(rooms: &mut RoomMap, req: RoomServiceRequest, tx: RoomService) { match req { // check whether a given room exists // the sender must provide a tokio::sync::oneshot sender to receive a response RoomServiceRequest::Exists(code, reply) => { reply.send(rooms.get(&code).is_some()).ok(); }, // send a websocket into the given room, starting it if it doesn't exist RoomServiceRequest::Join(code, ws) => { let room = match rooms.get(&code) { Some(rm) => rm, None => { let rm = room::start_room(code.clone(), tx); rooms.insert(code.clone(), rm); &rooms[&code] } }; room::add_connection(room, ws).await; }, // remove a room (called by the room task itself once there are no more connections to it) RoomServiceRequest::Remove(code) => { rooms.remove(&code); } } } // a task to manage a hashmap holding the room task senders // returns a sender to interface with the task pub fn start_room_server() -> RoomService { let (tx, mut rx) = mpsc::channel::(10); let txret = tx.clone(); tokio::spawn(async move { let mut rooms: RoomMap = HashMap::new(); while let Some(req) = rx.recv().await { handle_room_server_message(&mut rooms, req, tx.clone()).await; } }); txret }