pre-metrics

This commit is contained in:
2026-05-15 19:35:06 +02:00
parent 0b441b0759
commit 132057217d
43 changed files with 1170 additions and 170 deletions
+106 -1
View File
@@ -2,9 +2,14 @@ pub mod state;
use crate::config::AppConfig;
use crate::database::Database;
use crate::http::server::HttpServer;
use crate::repositories::Repositories;
use crate::udp::server::UdpServer;
use event_bus::EventBus;
use migration::{Migrator, MigratorTrait};
pub use state::AppState;
use std::sync::Arc;
use uuid::Uuid;
pub struct App {
pub state: AppState,
@@ -12,14 +17,53 @@ pub struct App {
impl App {
pub async fn build(config: AppConfig) -> Result<Self, Box<dyn std::error::Error>> {
// Initialize database connection
let db_manager = Database::init(&config.database.url).await?;
let db = db_manager.get_connection().clone();
// Run database migrations
Migrator::up(&db, None).await?;
// Initialize EventBus
let event_bus = Arc::new(EventBus::with_capacity(1024));
// Initialize shared repositories
let repositories = Repositories::new(db.clone(), event_bus.clone());
// Init one server if no one exist
let default_server = match repositories.server.get_default().await? {
Some(server) => server,
None => {
let new_server = repositories
.server
.create_with_args("default".to_string(), true)
.await?;
tracing::info!("Initialized default server");
new_server
}
};
// Init Token if no user exist
let init_token = if repositories.user.count().await? == 0 {
let token = Uuid::new_v4();
println!("+------------------------------------------------------------+");
println!("| NO USER FOUND IN DATABASE |");
println!("| Use the following token to create the first admin user: |");
println!("| |");
println!("| TOKEN: {} |", token);
println!("| |");
println!("+------------------------------------------------------------+");
Some(token)
} else {
None
};
let state = AppState {
db,
config: Arc::new(config),
repositories,
init_token,
default_server: Arc::new(default_server),
};
Ok(Self { state })
@@ -28,6 +72,67 @@ impl App {
pub async fn run(self) -> Result<(), Box<dyn std::error::Error>> {
tracing::info!("Starting services...");
tokio::select! {}
let config = self.state.config.clone();
// Initialize HTTP Server
let (http_server, http_shutdown_tx) = HttpServer::new(&config.network, self.state.clone());
// Initialize UDP service
let (udp_server, udp_shutdown_tx) = UdpServer::new(&config.network);
// On lance les serveurs dans des tâches séparées
let mut http_handle = tokio::spawn(http_server.run());
let mut udp_handle = tokio::spawn(udp_server.run());
// On arbitre : soit un signal arrive, soit une tâche se termine (erreur/crash)
tokio::select! {
res = &mut http_handle => {
tracing::error!("HTTP server stopped unexpectedly: {:?}", res);
}
res = &mut udp_handle => {
tracing::error!("UDP server stopped unexpectedly: {:?}", res);
}
_ = Self::shutdown_signal() => {
tracing::info!("Shutdown signal received, initiating graceful shutdown...");
}
}
// Dans tous les cas (Ctrl-C ou crash d'un service), on demande l'arrêt global
let _ = http_shutdown_tx.send(());
let _ = udp_shutdown_tx.send(());
// On attend que tout le monde ait fini de nettoyer
// (Note: join! supporte les handles déjà terminés ou annulés)
let _ = tokio::join!(http_handle, udp_handle);
tracing::info!("Closed the runtime application.");
Ok(())
}
async fn shutdown_signal() {
let ctrl_c = async {
tokio::signal::ctrl_c()
.await
.expect("failed to install Ctrl+C handler");
};
#[cfg(unix)]
let terminate = async {
tokio::signal::unix::signal(tokio::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 => {},
}
tracing::info!("Shutdown signal received");
}
}
+7
View File
@@ -1,4 +1,6 @@
use crate::config::AppConfig;
use crate::models::server;
use crate::repositories::Repositories;
use sea_orm::DatabaseConnection;
use std::sync::Arc;
@@ -6,4 +8,9 @@ use std::sync::Arc;
pub struct AppState {
pub db: DatabaseConnection,
pub config: Arc<AppConfig>,
pub repositories: Repositories,
pub init_token: Option<uuid::Uuid>,
pub default_server: Arc<server::Model>,
}
impl AppState {}