#[global_allocator] static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; use clap::Parser; use tracing_subscriber::EnvFilter; use anyhow::Result; use rustdb::RustDb; use rustdb::management; use rustdb_config::RustDbOptions; /// RustDb - MongoDB-compatible embedded database server #[derive(Parser, Debug)] #[command(name = "rustdb", version, about)] struct Cli { /// Path to JSON configuration file #[arg(short, long, default_value = "config.json")] config: String, /// Log level (trace, debug, info, warn, error) #[arg(short, long, default_value = "info")] log_level: String, /// Validate configuration without starting #[arg(long)] validate: bool, /// Run in management mode (JSON-over-stdin IPC for TypeScript wrapper) #[arg(long)] management: bool, } #[tokio::main] async fn main() -> Result<()> { let cli = Cli::parse(); // Initialize tracing - write to stderr so stdout is reserved for management IPC tracing_subscriber::fmt() .with_writer(std::io::stderr) .with_env_filter( EnvFilter::try_from_default_env() .unwrap_or_else(|_| EnvFilter::new(&cli.log_level)), ) .init(); // Management mode: JSON IPC over stdin/stdout if cli.management { tracing::info!("RustDb starting in management mode..."); return management::management_loop().await; } tracing::info!("RustDb starting..."); // Load configuration let options = RustDbOptions::from_file(&cli.config) .map_err(|e| anyhow::anyhow!("Failed to load config '{}': {}", cli.config, e))?; // Validate-only mode if cli.validate { match options.validate() { Ok(()) => { tracing::info!("Configuration is valid"); return Ok(()); } Err(e) => { tracing::error!("Validation error: {}", e); anyhow::bail!("Configuration validation failed: {}", e); } } } // Create and start server let mut db = RustDb::new(options).await?; db.start().await?; // Wait for shutdown signal tracing::info!("RustDb is running. Press Ctrl+C to stop."); tokio::signal::ctrl_c().await?; tracing::info!("Shutdown signal received"); db.stop().await?; tracing::info!("RustDb shutdown complete"); Ok(()) }