use std::net::SocketAddr; use std::path::PathBuf; use std::sync::Arc; use axum::extract::DefaultBodyLimit; use axum::Router; use tower_http::cors::CorsLayer; use tower_http::trace::TraceLayer; use can_service::config::Config; use can_service::{db, routes, verifier, AppState}; #[tokio::main] async fn main() -> anyhow::Result<()> { // Initialize tracing tracing_subscriber::fmt() .with_env_filter( tracing_subscriber::EnvFilter::try_from_default_env() .unwrap_or_else(|_| "can_service=info,tower_http=info".into()), ) .init(); // Load config let config_path = std::env::args() .nth(1) .map(PathBuf::from) .unwrap_or_else(|| PathBuf::from("config.yaml")); let config = Config::load(&config_path)?; tracing::info!("Loaded config, storage_root: {:?}", config.storage_root); // Ensure directories exist config.ensure_dirs()?; // Open database let db = db::open(&config.db_path())?; tracing::info!("Database initialized at {:?}", config.db_path()); let config = Arc::new(config); // Start background verifier verifier::start((*config).clone(), db.clone()); let state = AppState { config: config.clone(), db, }; // Build router let app = Router::new() .merge(routes::router()) .layer(DefaultBodyLimit::max(100 * 1024 * 1024)) // 100 MB .layer(TraceLayer::new_for_http()) .layer(CorsLayer::permissive()) .with_state(state); let addr = SocketAddr::from(([0, 0, 0, 0], 3210)); tracing::info!("CAN service listening on {}", addr); let listener = tokio::net::TcpListener::bind(addr).await?; axum::serve(listener, app).await?; Ok(()) }