use actix_web::{web, App, HttpServer, HttpResponse}; use anyhow::Result; use log::{info, error}; use std::sync::Arc; use tokio::sync::Mutex; mod api; mod monitor; mod anchor; mod models; mod db; mod config; mod payment_watcher; use config::Config; use db::Database; #[actix_web::main] async fn main() -> Result<()> { env_logger::init(); info!("🚀 Starting 4NK Certificator service..."); // Load configuration let config = Config::from_file("config.toml")?; info!("📄 Configuration loaded from config.toml"); // Initialize database connection let database = Database::new(&config.database.url).await?; info!("🗄️ Database connected"); // Run migrations database.run_migrations().await?; info!("✅ Database migrations applied"); // Initialize Prometheus metrics api::metrics_prometheus::init_metrics(); info!("📊 Prometheus metrics initialized"); // Wrap database in Arc for shared state let db = Arc::new(Mutex::new(database)); // Start background tasks let monitor_handle = tokio::spawn({ let config = config.clone(); let db = db.clone(); async move { monitor::start_monitoring(config, db).await } }); let payment_handle = tokio::spawn({ let config = config.clone(); let db = db.clone(); async move { payment_watcher::start_payment_watching(config, db).await } }); let anchor_handle = tokio::spawn({ let config = config.clone(); let db = db.clone(); async move { anchor::start_anchoring_loop(config, db).await } }); // Start HTTP server let bind_address = format!("{}:{}", config.server.host, config.server.port); info!("🌐 Starting HTTP server on {}", bind_address); let server = HttpServer::new(move || { App::new() .app_data(web::Data::new(db.clone())) .app_data(web::Data::new(config.clone())) .route("/health", web::get().to(health_check)) .route("/metrics", web::get().to(api::metrics_prometheus::metrics_handler)) .service( web::scope("/api/v1") .configure(api::configure_routes) ) }) .bind(&bind_address)? .run(); info!("✅ 4NK Certificator service started successfully"); // Await all tasks tokio::select! { res = server => { error!("HTTP server stopped: {:?}", res); } res = monitor_handle => { error!("Monitor task stopped: {:?}", res); } res = payment_handle => { error!("Payment watcher stopped: {:?}", res); } res = anchor_handle => { error!("Anchor task stopped: {:?}", res); } } Ok(()) } async fn health_check() -> HttpResponse { HttpResponse::Ok().json(serde_json::json!({ "status": "healthy", "service": "4nk_certificator", "version": env!("CARGO_PKG_VERSION") })) }