On continue le refactoring des sources
This commit is contained in:
@@ -78,3 +78,131 @@ pub use logs::{
|
||||
log_setup_get, log_setup_post, log_sse,
|
||||
};
|
||||
pub use server::{ApiRegistry, ApiRegistryEntry, Server, ServerBuilder, ServerInfo};
|
||||
|
||||
// ============================================================================
|
||||
// Singleton global du serveur
|
||||
// ============================================================================
|
||||
|
||||
use once_cell::sync::OnceCell;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
/// Instance globale unique du serveur PMOMusic
|
||||
///
|
||||
/// Ce singleton assure qu'une seule instance du serveur existe dans l'application.
|
||||
/// Il est initialisé une seule fois via [`init_server()`] et accessible partout
|
||||
/// via [`get_server()`].
|
||||
///
|
||||
/// # Exemple
|
||||
///
|
||||
/// ```ignore
|
||||
/// use pmoserver::{init_server, get_server_base_url};
|
||||
///
|
||||
/// // Initialiser le serveur global (idempotent - peut être appelé plusieurs fois)
|
||||
/// let server = init_server().await;
|
||||
///
|
||||
/// // Récupérer l'URL de base du serveur
|
||||
/// if let Some(url) = get_server_base_url() {
|
||||
/// println!("Server running at: {}", url);
|
||||
/// }
|
||||
/// ```
|
||||
static GLOBAL_SERVER: OnceCell<Arc<RwLock<Server>>> = OnceCell::new();
|
||||
|
||||
/// Initialise le serveur global unique depuis la configuration
|
||||
///
|
||||
/// Cette fonction est **idempotente** : elle peut être appelée plusieurs fois
|
||||
/// sans danger. Si le serveur est déjà initialisé, elle retourne simplement
|
||||
/// la référence existante.
|
||||
///
|
||||
/// # Configuration
|
||||
///
|
||||
/// Le serveur est créé via [`ServerBuilder::new_configured()`] qui lit
|
||||
/// la configuration depuis `pmoconfig`.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Une référence Arc vers le serveur global, encapsulé dans un RwLock
|
||||
/// pour permettre les accès concurrents mutables.
|
||||
///
|
||||
/// # Exemple
|
||||
///
|
||||
/// ```ignore
|
||||
/// use pmoserver::init_server;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() {
|
||||
/// // Première initialisation
|
||||
/// let server = init_server();
|
||||
///
|
||||
/// // Les appels suivants retournent la même instance
|
||||
/// let same_server = init_server();
|
||||
/// }
|
||||
/// ```
|
||||
pub fn init_server() -> Arc<RwLock<Server>> {
|
||||
GLOBAL_SERVER
|
||||
.get_or_init(|| {
|
||||
let server = ServerBuilder::new_configured().build();
|
||||
Arc::new(RwLock::new(server))
|
||||
})
|
||||
.clone()
|
||||
}
|
||||
|
||||
/// Récupère le serveur global s'il a été initialisé
|
||||
///
|
||||
/// Retourne `None` si [`init_server()`] n'a pas encore été appelé.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// - `Some(Arc<RwLock<Server>>)` si le serveur est initialisé
|
||||
/// - `None` si le serveur n'est pas encore initialisé
|
||||
///
|
||||
/// # Exemple
|
||||
///
|
||||
/// ```ignore
|
||||
/// use pmoserver::get_server;
|
||||
///
|
||||
/// if let Some(server) = get_server() {
|
||||
/// let srv = server.read().await;
|
||||
/// println!("Server is running at: {}", srv.base_url());
|
||||
/// } else {
|
||||
/// println!("Server not initialized yet");
|
||||
/// }
|
||||
/// ```
|
||||
pub fn get_server() -> Option<Arc<RwLock<Server>>> {
|
||||
GLOBAL_SERVER.get().cloned()
|
||||
}
|
||||
|
||||
/// Récupère l'URL de base du serveur global
|
||||
///
|
||||
/// Fonction helper qui extrait directement l'URL de base sans avoir
|
||||
/// à manipuler le RwLock manuellement.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// - `Some(String)` contenant l'URL complète (ex: "http://192.168.1.10:8080")
|
||||
/// - `None` si le serveur n'est pas encore initialisé
|
||||
///
|
||||
/// # Exemple
|
||||
///
|
||||
/// ```ignore
|
||||
/// use pmoserver::get_server_base_url;
|
||||
///
|
||||
/// if let Some(url) = get_server_base_url() {
|
||||
/// let stream_url = format!("{}/api/stream", url);
|
||||
/// println!("Stream available at: {}", stream_url);
|
||||
/// }
|
||||
/// ```
|
||||
pub fn get_server_base_url() -> Option<String> {
|
||||
GLOBAL_SERVER.get().map(|server| {
|
||||
// Utiliser try_read() pour éviter de bloquer
|
||||
// Si le lock est occupé, on retourne quand même l'URL
|
||||
// car elle ne change pas après l'initialisation
|
||||
if let Ok(srv) = server.try_read() {
|
||||
srv.base_url()
|
||||
} else {
|
||||
// Fallback: bloquer jusqu'à obtenir le lock
|
||||
// (ne devrait jamais arriver en pratique)
|
||||
futures::executor::block_on(async { server.read().await.base_url() })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user