xecute-cli 0.1.2

NestJS-style project and resource generator for Xecute
use crate::{app_module, configs::Config};
use super::{logging, shutdown};
use std::{future::IntoFuture, sync::Arc};
use tokio::sync::Notify;

pub async fn run() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    crate::configs::load_env()?;
    logging::init()?;
    let config = Config::from_env()?;
    let app = super::router(app_module::AppModule::router()?, &config);
    let listener = tokio::net::TcpListener::bind(config.bind_address).await?;
    tracing::info!(address = %listener.local_addr()?, "server listening");
    let draining = Arc::new(Notify::new());
    let shutdown_started = draining.clone();
    let server = axum::serve(listener, app.into_make_service_with_connect_info::<std::net::SocketAddr>())
        .with_graceful_shutdown(async move {
            shutdown::signal().await;
            tracing::info!("shutdown requested; draining requests");
            shutdown_started.notify_one();
        }).into_future();
    tokio::pin!(server);
    tokio::select! {
        result = &mut server => result?,
        _ = draining.notified() => {
            match tokio::time::timeout(config.shutdown_grace, &mut server).await {
                Ok(result) => result?,
                Err(error) => {
                    tracing::error!("shutdown drain deadline exceeded");
                    return Err(error.into());
                }
            }
        }
    }
    tracing::info!("server stopped");
    Ok(())
}