mirror of
https://github.com/R0m1k3/xtremflow.git
synced 2026-10-18 04:39:41 +02:00
Logos, guide TV et fluidité : couper le flot de requêtes mortes
Logos absents : l'hébergeur des picons du fournisseur répond 503 sur tout, y compris sa racine (serveur en maintenance). Le proxy relayait ce 503 au navigateur, qui redemandait chaque logo à chaque affichage de la grille — des centaines de requêtes sortantes mortes par seconde. - Un statut >= 400 sur une image rend désormais un pixel transparent avec `Cache-Control: max-age=600`, au lieu de propager l'erreur - Après trois échecs consécutifs, l'hôte est marqué hors service cinq minutes : plus aucun appel sortant, réponse servie localement - Le corps d'erreur amont est drainé, sinon la connexion restait ouverte jusqu'au timeout Guide TV très lent (4 à 8 s par chaîne dans les logs) : `player_api` demande un appel par chaîne, et le panneau met ~4 s à répondre — une grille de trente chaînes dépassait la minute. - Le dump `xmltv.php` du panneau passe en premier : une requête couvre toutes les chaînes, réutilisée trois heures - L'interrogation chaîne par chaîne reste le repli, puis la source XMLTV externe - Une source XMLTV en échec n'est plus retéléchargée à chaque consultation : quinze minutes de recul - Index borné à 48 h en avant : un dump national couvre sept jours pour un millier de chaînes, soit des centaines de Mo pour un guide qui n'affiche que le programme courant Lecture saccadée : le relais FFmpeg -> navigateur de `/turbo.ts` ne transmettait pas la pause du client à la source. Un lecteur plus lent que le flux laissait FFmpeg produire à pleine vitesse et le serveur empilait les paquets en mémoire, d'où la dérive derrière le direct. La contre-pression est maintenant propagée (`pipeWithBackpressure`). Le serveur tourne sur un seul isolate : le flot de requêtes mortes et les attentes EPG de plusieurs secondes partageaient la boucle d'événements avec les paquets vidéo. Tests ajoutés : cache d'échecs par hôte, contre-pression du relais, priorité des sources EPG, recul après échec XMLTV, horizon d'index. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2151f2820c
commit
b6ca9dab96
11 files changed
+716
-78
No files matched your search
@@ -0,0 +1,49 @@
|
||||
import 'dart:async';
|
||||
|
||||
/// Relaie [source] vers le client en conservant la contre-pression.
|
||||
///
|
||||
/// POURQUOI : un `StreamController` nu ne transmet pas la pause de son
|
||||
/// abonné à la source. Quand le navigateur lit plus lentement que FFmpeg ne
|
||||
/// produit — réseau domestique, onglet en arrière-plan —, le serveur empilait
|
||||
/// donc les paquets en mémoire sans jamais ralentir le producteur : la
|
||||
/// consommation grimpe et la lecture dérive derrière le direct, ce qui se voit
|
||||
/// à l'écran comme des saccades.
|
||||
///
|
||||
/// [onStop] est appelé une seule fois, quand le client se déconnecte ou que la
|
||||
/// source se termine : c'est là qu'on tue le processus FFmpeg, sinon il en
|
||||
/// reste un par zapping.
|
||||
Stream<List<int>> pipeWithBackpressure(
|
||||
Stream<List<int>> source, {
|
||||
required void Function() onStop,
|
||||
}) {
|
||||
late final StreamController<List<int>> controller;
|
||||
late final StreamSubscription<List<int>> subscription;
|
||||
var stopped = false;
|
||||
|
||||
void stop() {
|
||||
if (stopped) return;
|
||||
stopped = true;
|
||||
onStop();
|
||||
}
|
||||
|
||||
controller = StreamController<List<int>>(
|
||||
onPause: () => subscription.pause(),
|
||||
onResume: () => subscription.resume(),
|
||||
onCancel: () {
|
||||
final cancelled = subscription.cancel();
|
||||
stop();
|
||||
return cancelled;
|
||||
},
|
||||
);
|
||||
|
||||
subscription = source.listen(
|
||||
controller.add,
|
||||
onError: controller.addError,
|
||||
onDone: () {
|
||||
controller.close();
|
||||
stop();
|
||||
},
|
||||
);
|
||||
|
||||
return controller.stream;
|
||||
}
|
||||
Reference in new issue
Block a user