//! Domain definitions and implementation of common chat logic. use std::ops::Deref; use std::sync::Arc; use anyhow::Result; use prometheus::Registry as MetricsRegistry; use crate::clustering::broadcast::Broadcasting; use crate::clustering::{ClusterConfig, ClusterMetadata, LavinaClient}; use crate::dialog::DialogRegistry; use crate::player::{PlayerConnection, PlayerId, PlayerRegistry}; use crate::repo::Storage; use crate::room::{RoomHandle, RoomId, RoomInfo, RoomRegistry}; pub mod auth; pub mod clustering; pub mod dialog; pub mod player; pub mod prelude; pub mod repo; pub mod room; pub mod terminator; mod table; #[derive(Clone)] pub struct LavinaCore { services: Arc, } impl Deref for LavinaCore { type Target = Services; fn deref(&self) -> &Self::Target { &self.services } } impl LavinaCore { pub async fn connect_to_player(&self, player_id: &PlayerId) -> PlayerConnection { self.services.players.connect_to_player(&self, player_id).await } pub async fn get_room(&self, room_id: &RoomId) -> Option { self.services.rooms.get_room(&self.services, room_id).await } pub async fn create_player(&self, player_id: &PlayerId) -> Result<()> { self.services.storage.create_user(player_id.as_inner()).await } pub async fn get_all_rooms(&self) -> Vec { self.services.rooms.get_all_rooms().await } pub async fn stop_player(&self, player_id: &PlayerId) -> Result> { self.services.players.stop_player(player_id).await } } pub struct Services { pub(crate) players: PlayerRegistry, pub(crate) rooms: RoomRegistry, pub(crate) dialogs: DialogRegistry, pub(crate) broadcasting: Broadcasting, pub(crate) client: LavinaClient, pub(crate) storage: Storage, pub(crate) cluster_metadata: ClusterMetadata, } impl LavinaCore { pub async fn new( metrics: &mut MetricsRegistry, cluster_config: ClusterConfig, storage: Storage, ) -> Result { // TODO shutdown all services in reverse order on error let broadcasting = Broadcasting::new(); let client = LavinaClient::new(cluster_config.addresses.clone()); let rooms = RoomRegistry::new(metrics)?; let dialogs = DialogRegistry::new(); let players = PlayerRegistry::empty(metrics)?; let services = Services { players, rooms, dialogs, broadcasting, client, storage, cluster_metadata: cluster_config.metadata, }; Ok(LavinaCore { services: Arc::new(services), }) } pub async fn shutdown(self) -> Storage { let _ = self.players.shutdown_all().await; let services = match Arc::try_unwrap(self.services) { Ok(e) => e, Err(_) => { panic!("failed to acquire services ownership on shutdown"); } }; let _ = services.players.shutdown(); let _ = services.dialogs.shutdown(); let _ = services.rooms.shutdown(); services.storage } }