#![forbid(unsafe_code, unused_must_use)] #![deny(clippy::unwrap_used, clippy::panic, clippy::expect_used)] use clap::{CommandFactory, Parser}; use tracing::{error, info}; use tracing_subscriber::{ Layer, filter::LevelFilter, fmt, layer::SubscriberExt, registry::Registry, reload, util::SubscriberInitExt, }; use crate::cli::{Cli, handle_sub_command}; mod cli; mod config; mod connector; mod db; mod service; #[tokio::main] async fn main() { // install a global subscriber for logging let reload_handle = install_tracing_subscriber(); // Load configuration settings let settings = match config::settings::Settings::load() { Ok(s) => s, Err(e) => { error!("Failed to load configuration: {}", e); std::process::exit(1); } }; reload_handle .modify(|filter| *filter = Box::new(settings.log.level)) .inspect_err(|e| { error!( "Failed to set log level: {}. Continuing with default level.", e ) }) // ignore errors here since we can still run with the default log level .ok(); // print the loaded settings for debugging // info!("Loaded settings: {:#?}", settings); let cli = Cli::parse(); if cli.serve { info!("Starting master server..."); if let Err(e) = service::start_master_server(settings, cli).await { error!("Failed to start master server: {}", e); std::process::exit(1); } } else if let Some(command) = cli.command { handle_sub_command(&settings, command) .await .unwrap_or_else(|e| { error!("Error handling command: {}", e); std::process::exit(1); }); } else { error!("No mode specified."); // display help message #[allow(clippy::expect_used)] Cli::command() .print_help() .expect("Failed to print help message"); std::process::exit(1); } } fn install_tracing_subscriber() -> reload::Handle + Send + Sync>, Registry> { let filter = LevelFilter::INFO; let (filter_layer, reload_handle) = reload::Layer::new(Box::new(fmt::layer().with_filter(filter)) as Box + Send + Sync>); tracing_subscriber::registry() .with(filter_layer) .with(fmt::Layer::default()) .init(); reload_handle }