server-watchdog 0.1.0

A server monitoring and remote control tool via messenger.
Documentation
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use clap::{Parser, Subcommand};
use log::{debug, trace};
use tokio::sync::mpsc;
use crate::application::client::ClientLoader;
use crate::application::event::checker::{GeneralEventChecker, HealthEventChecker, LogEventChecker};
use crate::application::event::receiver::EventManager;
use crate::application::handler::{GeneralHandler, MessageHandler};
use crate::application::worker::WorkerRunner;
use crate::domain::chat::ChatList;
use crate::domain::config::{Config, EventSubscribeList};
use crate::domain::file_accessor::FileAccessor;
use crate::infrastructure::cli::client::ClientCommands;
use crate::infrastructure::cli::event::EventCommands;
use crate::infrastructure::cli::password::PasswordCommands;
use crate::infrastructure::cli::server::ServerCommands;
use crate::infrastructure::client::{ClientManager, MessageAdapter};
use crate::infrastructure::common::file_accessor::{get_chat_list_file_accessor, get_config_file_accessor, get_event_subscribe_file_accessor};
use crate::infrastructure::config::{ClientConfigAdapter, EventConfigAdapter, ServerConfigAdapter};
use crate::infrastructure::config::auth::AuthAdapter;
use crate::infrastructure::server::{ConfigServerRepository, GeneralServerManager};

#[derive(Parser)]
#[derive(Debug)]
pub struct Cli {

    #[command(subcommand)]
    pub command: Commands
}

#[derive(Subcommand)]
#[derive(Debug)]
pub enum Commands {
    Server {
        #[command(subcommand)]
        command: ServerCommands
    },
    Client {
        #[command(subcommand)]
        command: ClientCommands
    },
    Password {
        #[command(subcommand)]
        command: PasswordCommands
    },
    Event {
        #[command(subcommand)]
        command: EventCommands
    },
    Run
}

impl Commands {
    pub async fn run(&self) {
        trace!("command start: {:?}", &self);
        let config_file_accessor: Arc<dyn FileAccessor<Config> + Send + Sync> = Arc::new(get_config_file_accessor());
        match self {
            Commands::Password { command } => {
                let chat_list_file_accessor: Arc<dyn FileAccessor<ChatList> + Send + Sync> = Arc::new(get_chat_list_file_accessor());
                let mut auth_adapter = AuthAdapter::new(config_file_accessor.clone(), chat_list_file_accessor);
                auth_adapter.init().await;
                let auth_config = Box::new(auth_adapter);
                command.run(auth_config).await
            }
            Commands::Server { command } => {
                debug!("server command");
                let server_config = ServerConfigAdapter::new(
                    config_file_accessor.clone()
                );
                let server_config = Box::new(server_config);
                command.run(server_config).await
            },
            Commands::Client { command } => {
                debug!("client command");
                let client_config = ClientConfigAdapter::new(
                    config_file_accessor.clone()
                );
                let client_config = Box::new(client_config);
                command.run(client_config).await
            },
            Commands::Event { command } => {
                debug!("event command");
                let subscribe_file_accessor: Arc<dyn FileAccessor<EventSubscribeList> + Send + Sync> = Arc::new(get_event_subscribe_file_accessor());

                let event_config = EventConfigAdapter::new(
                    config_file_accessor.clone(),
                    subscribe_file_accessor
                );
                let event_config = Box::new(event_config);
                command.run(event_config).await
            },
            Commands::Run => {
                debug!("run command");
                let chat_list_file_accessor: Arc<dyn FileAccessor<ChatList> + Send + Sync> = Arc::new(get_chat_list_file_accessor());
                let subscribe_file_accessor: Arc<dyn FileAccessor<EventSubscribeList> + Send + Sync> = Arc::new(get_event_subscribe_file_accessor());

                let worker_runner = Arc::new(Mutex::new(WorkerRunner::new()));

                let mut client_manager = ClientManager::new(
                    worker_runner.clone(),
                    Arc::new(Mutex::new(HashMap::new())),
                    config_file_accessor.clone()
                );
                let _ = client_manager.load_clients().await;

                let message_gateway = Arc::new(MessageAdapter::new(Arc::new(client_manager.clone())));
                let mut rx = client_manager.run().await;

                let mut auth_adapter = AuthAdapter::new(config_file_accessor.clone(), chat_list_file_accessor.clone());
                auth_adapter.init().await;

                let mut server_repository = ConfigServerRepository::new(
                    config_file_accessor.clone()
                );
                server_repository.load().await;

                let event_config_adapter = Arc::new(EventConfigAdapter::new(
                    config_file_accessor.clone(),
                    subscribe_file_accessor.clone()
                ));

                let server_manager = Arc::new(GeneralServerManager::new(Box::new(server_repository)));

                let mut handler = GeneralHandler::new(
                    message_gateway.clone(),
                    server_manager.clone(),
                    Box::new(auth_adapter),
                    event_config_adapter.clone(),
                    event_config_adapter.clone()
                );

                let (tx, rx_event) = mpsc::channel(32);
                let event_manager = EventManager::new(
                    rx_event,
                    message_gateway.clone(),
                    chat_list_file_accessor,
                    subscribe_file_accessor
                );

                {
                    worker_runner.lock().unwrap().run(Box::new(event_manager));
                }

                let event_checker = GeneralEventChecker::new(
                    config_file_accessor.clone(),
                    server_manager.clone(),
                    tx,
                    Box::new(HealthEventChecker::new()),
                    Box::new(LogEventChecker::new())
                );

                event_checker.init().await;

                tokio::spawn(async move {
                    loop {
                        if let Some(message) = rx.recv().await {
                            handler.handle(message).await;
                        }
                    }
                });
                println!("=== Run ===");
                tokio::signal::ctrl_c().await.unwrap();
                println!("=== Shutdown ===");
            }
        }
        trace!("command end");
    }
}