use std::collections::HashMap; use std::sync::{Arc, Mutex}; use actix::{Actor, Context, Handler, Message, Recipient}; use emgauwa_lib::errors::DatabaseError; use emgauwa_lib::models::Controller; use emgauwa_lib::types::{ControllerUid, ControllerWsAction}; use futures::executor::block_on; use sqlx::{Pool, Sqlite}; #[derive(Message)] #[rtype(result = "Result<(), DatabaseError>")] pub struct DisconnectController { pub controller_uid: ControllerUid, } #[derive(Message)] #[rtype(result = "Result<(), DatabaseError>")] pub struct ConnectController { pub address: Recipient, pub controller: Controller, } pub struct AppServer { pub pool: Pool, pub connected_controllers: Arc>>, } impl AppServer { pub fn new(pool: Pool) -> AppServer { AppServer { pool, connected_controllers: Arc::new(Mutex::new(HashMap::new())), } } } impl Actor for AppServer { type Context = Context; } impl Handler for AppServer { type Result = Result<(), DatabaseError>; fn handle(&mut self, msg: DisconnectController, _ctx: &mut Self::Context) -> Self::Result { let mut pool_conn = block_on(self.pool.acquire()).unwrap(); let mut data = self.connected_controllers.lock().unwrap(); if let Some(controller) = data.remove(&msg.controller_uid) { if let Err(err) = block_on(controller.c.update_active(&mut pool_conn, false)) { log::error!( "Failed to mark controller {} as inactive: {:?}", controller.c.uid, err ); } } Ok(()) } } impl Handler for AppServer { type Result = Result<(), DatabaseError>; fn handle(&mut self, msg: ConnectController, _ctx: &mut Self::Context) -> Self::Result { let mut data = self.connected_controllers.lock().unwrap(); data.insert(msg.controller.c.uid.clone(), msg.controller); Ok(()) } }