use anyhow::Result;
use clap::Parser;
use dotenvy::dotenv;
use opencrates::server::run_server;
use opencrates::utils::{config::OpenCratesConfig, logging};
use tokio::signal;
use tracing::Level;
#[cfg(not(feature = "tracing"))]
use log::{info, warn};
#[cfg(feature = "tracing")]
use tracing::{info, warn};
#[derive(Parser)]
#[command(name = "opencrates-server")]
#[command(about = "OpenCrates standalone server")]
#[command(version)]
struct Args {
#[arg(long, default_value = "0.0.0.0")]
host: String,
#[arg(short, long, default_value = "8080")]
port: u16,
#[arg(short, long, default_value = "4")]
workers: usize,
#[arg(short, long)]
config: Option<String>,
#[arg(short, long)]
debug: bool,
#[arg(long)]
metrics: bool,
#[arg(long)]
admin: bool,
}
#[tokio::main]
async fn main() -> Result<()> {
dotenv().ok();
let args = Args::parse();
let level = if args.debug {
Level::DEBUG
} else {
Level::INFO
};
logging::init(level);
info!("Starting OpenCrates Server v{}", env!("CARGO_PKG_VERSION"));
let config = OpenCratesConfig::default();
info!("Server will bind to: {}:{}", args.host, args.port);
if args.metrics {
info!("Metrics endpoint enabled at /metrics");
}
if args.admin {
info!("Admin API enabled");
}
tokio::spawn(async move {
shutdown_signal().await;
warn!("Shutdown signal received, starting graceful shutdown...");
});
info!("OpenCrates Server starting on {}:{}", args.host, args.port);
run_server(config).await?;
info!("OpenCrates Server shutdown complete");
Ok(())
}
async fn shutdown_signal() {
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 => {},
}
}