use std::sync::mpsc; use clap::Parser; use nuchat::Config; use nuchat::app; use tokio::net::TcpListener; use tokio::signal; use tracing::info; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; #[derive(Parser, Debug)] #[command(version, about, long_about = None)] struct Args { /// Port to run server on #[arg(long, default_value_t = 7000)] port: u32, /// Host to run server on #[arg(long, default_value = "127.0.0.1")] host: String, /// Admin secret to use, leave blank to disable #[arg(long)] admin_secret: Option, } #[tokio::main] async fn main() { let args = Args::parse(); let config = BinConfig::from_args(args); tracing_subscriber::registry() .with( tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| { format!("{}=debug,tower_http=debug", env!("CARGO_CRATE_NAME")).into() }), ) .with(tracing_subscriber::fmt::layer().with_target(false)) .init(); let listener = TcpListener::bind(format!("{}:{}", config.0.host, config.0.port)) .await .unwrap(); tracing::debug!("listening on {}", listener.local_addr().unwrap()); let (app, rx) = app(&config.0); axum::serve(listener, app) .with_graceful_shutdown(shutdown_signal(rx)) .await .unwrap(); info!("Server stopped"); } #[allow(clippy::unused_async)] #[allow(unused)] async fn await_shutdown(rx: mpsc::Receiver) -> Result { rx.recv() } async fn shutdown_signal(rx: mpsc::Receiver) { let endpoint = tokio::spawn(async move { rx.recv() }).into_future(); let ctrl_c = async { signal::ctrl_c() .await .expect("failed to install Ctrl+C handler"); }; #[cfg(unix)] let terminate = async { signal::unix::signal(signal::unix::SignalKind::terminate()) .expect("failed to install signal handler") .recv() .await; }; #[cfg(not(unix))] let terminate = std::future::pending::<()>(); tokio::select! { () = ctrl_c => {}, () = terminate => {}, _ = endpoint => {}, } info!("Shutting server down gracefully..."); } struct BinConfig(Config); impl BinConfig { fn from_args(args: Args) -> Self { Self(Config { port: args.port, host: args.host, admin_secret: args.admin_secret, }) } }