2025-10-01 09:45:33 +00:00

114 lines
3.0 KiB
Rust

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<Mutex> 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")
}))
}