push-kvzwrolnknzx #86

Merged
eric merged 13 commits from push-kvzwrolnknzx into main 2026-04-04 12:59:11 +02:00
2 changed files with 50 additions and 8 deletions
Showing only changes of commit 97a82f4e1d - Show all commits

View File

@@ -360,4 +360,46 @@ fn transform_external_cover_url(url: &str) -> String {
1. **Nouveau** : `pmocovers/src/proxy.rs` - Endpoint de proxy
2. **Modifier** : `pmocontrol/src/pmoserver_ext.rs` - Transformer les album_art_uri
3. **Modifier** : `pmocontrol/src/sse.rs` - Transformer les album_art_uri dans les événements
3. **Modifier** : `pmocontrol/src/sse.rs` - Transformer les album_art_uri dans les événements
---
## Plan: Passer le SSE en mode Async
### Contexte
Le SSE de PMO Control est **déjà async** (fonctions `pub async fn`), mais le traitement des événements utilise des fonctions **synchrones** (`fn renderer_event_to_payload``transform_cover_url_sync`). Cela nécessite des workarounds (threads avec runtime tokio séparés).
### Problèmes actuels
1. **Nested runtime**: `std::thread::spawn` avec `tokio::runtime::Runtime::new()` dans chaque appel
2. **Performance dégradée**: Création d'un thread par URL de cover
3. **Code complexe**: Workarounds pour exécuter de l'async dans du sync
### Solution
Rendre le traitement des événements **entièrement async** :
1. **Modifier** `renderer_event_to_payload``async fn renderer_event_to_payload`
2. **Modifier** `transform_cover_url_sync``transform_cover_url` (async) avec `.await` direct
3. **Supprimer** le workaround `proxy_cover_url_sync` dans `pmocovers` (quand les .await fonctionnent)
### Avantages attendus
1. **Fluidité accrue**: Pas de thread par cover,真正的 async/await
2. **Meilleure réactivité**: Pas de blocking sur les événements SSE
3. **Code plus propre**: Plus de workarounds, plus de runtime imbriqué
4. **Meilleure scalabilité**: Plus de création de thread
### Fichiers à modifier
1. `pmocontrol/src/sse.rs`:
- `renderer_event_to_payload``async fn`
- `media_server_event_to_payload``async fn`
- `all_events_sse`: utiliser les versions async
2. `pmocontrol/src/pmoserver_ext.rs`:
- Utiliser `transform_cover_url` (async) avec `.await` au lieu de `transform_cover_url_sync`
3. `pmocontrol/src/control_point.rs` (si nécessaire):
- Adapter les appels aux fonctions async

View File

@@ -248,7 +248,7 @@ pub enum UnifiedEventPayload {
/// Cette fonction centralise la conversion pour éviter la duplication de code
/// entre les différents streams SSE (renderers-only et all-events).
#[cfg(feature = "pmoserver")]
fn renderer_event_to_payload(
async fn renderer_event_to_payload(
event: RendererEvent,
timestamp: chrono::DateTime<chrono::Utc>,
base_url: &pmoserver::BaseUrl,
@@ -281,7 +281,7 @@ fn renderer_event_to_payload(
title: metadata.title,
artist: metadata.artist,
album: metadata.album,
album_art_uri: transform_cover_url_sync(metadata.album_art_uri.as_deref(), base_url),
album_art_uri: transform_cover_url(metadata.album_art_uri.as_deref(), base_url).await,
timestamp,
},
RendererEvent::QueueUpdated { id, queue_length } => RendererEventPayload::QueueUpdated {
@@ -361,7 +361,7 @@ fn renderer_event_to_payload(
/// Cette fonction centralise la conversion pour éviter la duplication de code
/// entre les différents streams SSE (servers-only et all-events).
#[cfg(feature = "pmoserver")]
fn media_server_event_to_payload(
async fn media_server_event_to_payload(
event: MediaServerEvent,
timestamp: chrono::DateTime<chrono::Utc>,
) -> MediaServerEventPayload {
@@ -480,7 +480,7 @@ pub async fn renderer_events_sse(
// Regular events from the control point
Some(event) = rx_tokio.recv() => {
let timestamp = chrono::Utc::now();
let payload = renderer_event_to_payload(event, timestamp, &base_url);
let payload = renderer_event_to_payload(event, timestamp, &base_url).await;
if let Ok(json) = serde_json::to_string(&payload) {
yield Ok::<_, axum::Error>(Event::default().event("renderer").data(json));
@@ -602,7 +602,7 @@ pub async fn media_server_events_sse(
// Regular events from the control point
Some(event) = rx_tokio.recv() => {
let timestamp = chrono::Utc::now();
let payload = media_server_event_to_payload(event, timestamp);
let payload = media_server_event_to_payload(event, timestamp).await;
if let Ok(json) = serde_json::to_string(&payload) {
yield Ok::<_, axum::Error>(Event::default().event("media_server").data(json));
@@ -758,7 +758,7 @@ pub async fn all_events_sse(
tokio::select! {
Some(event) = renderer_rx_tokio.recv() => {
let timestamp = chrono::Utc::now();
let renderer_payload = renderer_event_to_payload(event, timestamp, &base_url);
let renderer_payload = renderer_event_to_payload(event, timestamp, &base_url).await;
let payload = UnifiedEventPayload::Renderer(renderer_payload);
@@ -768,7 +768,7 @@ pub async fn all_events_sse(
}
Some(event) = server_rx_tokio.recv() => {
let timestamp = chrono::Utc::now();
let server_payload = media_server_event_to_payload(event, timestamp);
let server_payload = media_server_event_to_payload(event, timestamp).await;
let payload = UnifiedEventPayload::MediaServer(server_payload);
if let Ok(json) = serde_json::to_string(&payload) {