pre-metrics
This commit is contained in:
+106
-1
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
Reference in New Issue
Block a user