#[cfg(not(coverage))]
#[tokio::main]
async fn main() -> anyhow::Result<()> {
use clap::Parser;
use tracing::info;
let cli = pulpod::Cli::parse();
match &cli.command {
Some(pulpod::CliCommand::Mcp) => {
let server = pulpod::build_mcp_server(&cli).await?;
pulpod::mcp::run_stdio(server).await?;
}
None => {
let config = pulpod::config::load(&cli.config)?;
let data_dir = std::path::PathBuf::from(config.data_dir());
let _log_guard = pulpod::init_tracing(Some(&data_dir), config.node.log_retain_days)?;
let (app, addr, shutdown_handle) = pulpod::build_app(&cli).await?;
let listener = tokio::net::TcpListener::bind(&addr).await?;
let (shutdown_done_tx, shutdown_done_rx) = tokio::sync::oneshot::channel::<()>();
let server = axum::serve(listener, app).with_graceful_shutdown(async move {
shutdown_signal(shutdown_handle).await;
let _ = shutdown_done_tx.send(());
});
tokio::select! {
result = server => result?,
() = async {
let _ = shutdown_done_rx.await;
tokio::time::sleep(std::time::Duration::from_secs(3)).await;
} => {
info!("Streaming connections still open — forcing shutdown");
}
}
info!("pulpod shut down cleanly");
}
}
Ok(())
}
#[cfg(not(coverage))]
async fn shutdown_signal(handle: pulpod::ShutdownHandle) {
use tracing::info;
let ctrl_c = async {
tokio::signal::ctrl_c()
.await
.expect("failed to install Ctrl+C handler");
};
#[cfg(unix)]
let terminate = async {
tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate())
.expect("failed to install SIGTERM handler")
.recv()
.await;
};
#[cfg(not(unix))]
let terminate = std::future::pending::<()>();
tokio::select! {
() = ctrl_c => {},
() = terminate => {},
}
info!("Shutdown signal received, stopping background tasks...");
handle.shutdown();
}
#[cfg(coverage)]
fn main() {}