Files
pmomusic/pmosource/src/pmoserver_impl.rs

120 lines
3.6 KiB
Rust

//! # Implémentation du trait MusicSourceExt pour pmoserver::Server
//!
//! Ce module enrichit `pmoserver::Server` avec les fonctionnalités de gestion
//! de sources musicales en implémentant le trait [`MusicSourceExt`](crate::MusicSourceExt).
//!
//! ## Architecture
//!
//! `pmosource` étend `pmoserver::Server` sans que `pmoserver` connaisse `pmosource`.
//! C'est le pattern d'extension utilisé par tous les crates de l'écosystème PMOMusic.
//!
//! ## Exemple d'utilisation
//!
//! ```rust,no_run
//! use pmosource::MusicSourceExt;
//! use pmoserver::ServerBuilder;
//!
//! # async fn example() -> anyhow::Result<()> {
//! let mut server = ServerBuilder::new("MyApp", "http://localhost:3000", 3000).build();
//!
//! // Initialiser le système de sources (enregistre l'API)
//! server.init_music_sources().await?;
//!
//! // Le trait MusicSourceExt est automatiquement disponible
//! let source = Arc::new(MySource::new());
//! server.register_music_source(source).await;
//!
//! server.start().await;
//! # Ok(())
//! # }
//! ```
#[cfg(feature = "server")]
use crate::api::{
create_sources_router, get_source, list_all_sources, register_source, unregister_source,
SourcesApiDoc,
};
#[cfg(feature = "server")]
use crate::pmoserver_ext::MusicSourceExt;
#[cfg(feature = "server")]
use crate::MusicSource;
#[cfg(feature = "server")]
use anyhow::Result;
#[cfg(feature = "server")]
use pmoserver::Server;
#[cfg(feature = "server")]
use std::sync::Arc;
#[cfg(feature = "server")]
use tracing::info;
#[cfg(feature = "server")]
use utoipa::OpenApi;
#[cfg(feature = "server")]
#[async_trait::async_trait]
impl MusicSourceExt for Server {
async fn init_music_sources(&mut self) -> Result<()> {
info!("Initializing music sources management system...");
// Créer le router pour l'API des sources
let router = create_sources_router();
// Créer la documentation OpenAPI
let openapi = SourcesApiDoc::openapi();
// Enregistrer l'API avec Swagger UI
// Le router sera nesté automatiquement sous /api/sources par add_openapi
// Routes finales: /api/sources, /api/sources/{id}, etc.
// Swagger UI sera disponible à /swagger-ui/sources
self.add_openapi(router, openapi, "sources").await;
info!("✅ Music sources API registered at /api/sources");
info!(" Swagger UI available at /swagger-ui/sources");
Ok(())
}
async fn register_music_source(&mut self, source: Arc<dyn MusicSource>) {
let source_id = source.id().to_string();
let source_name = source.name().to_string();
info!("Registering music source: {} ({})", source_name, source_id);
register_source(source).await;
info!("✅ Source '{}' registered successfully", source_name);
}
async fn unregister_music_source(&mut self, source_id: &str) -> bool {
info!("Unregistering music source: {}", source_id);
let result = unregister_source(source_id).await;
if result {
info!("✅ Source '{}' unregistered successfully", source_id);
} else {
tracing::warn!("⚠️ Source '{}' not found", source_id);
}
result
}
async fn list_music_sources(&self) -> Vec<Arc<dyn MusicSource>> {
list_all_sources().await
}
async fn get_music_source(&self, source_id: &str) -> Option<Arc<dyn MusicSource>> {
get_source(source_id).await
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_trait_implemented() {
// Ce test vérifie simplement que le trait est bien implémenté
// Les tests fonctionnels nécessiteraient un serveur et des sources réelles
}
}