wilenPxs commited on
Commit
fbdaead
·
1 Parent(s): 77a0a72

UI: suivi resilient au proxy HF (retry au lieu de planter sur reponse non-JSON)

Browse files
Files changed (1) hide show
  1. app/web/templates/index.html +35 -6
app/web/templates/index.html CHANGED
@@ -440,8 +440,10 @@
440
  'use strict';
441
 
442
  const POLL_MS = 1000;
 
443
  let currentJobId = null;
444
  let pollTimer = null;
 
445
  let activeTab = "exercice";
446
  let loadedFiles = []; // [{filename, content}]
447
  let jobResults = []; // résultats par fichier
@@ -727,6 +729,7 @@ async function run() {
727
 
728
  if (pollTimer) { clearTimeout(pollTimer); pollTimer = null; }
729
  currentJobId = null;
 
730
  jobResults = []; activeResultIdx = 0;
731
  document.getElementById("run-btn").disabled = true;
732
  hideStatus();
@@ -759,12 +762,27 @@ async function run() {
759
  async function poll() {
760
  if (!currentJobId) return;
761
  try {
762
- const res = await fetch(`/api/jobs/${currentJobId}`);
763
- const data = await res.json();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
764
  jobResults = data.results || [];
765
  if (data.status === "running") {
766
  setProgress("running", data.step_label || "…", `${data.files_done}/${data.files_total}`);
767
- // Affiche au fil de l'eau le dernier fichier terminé.
768
  if (jobResults.length && activeResultIdx < jobResults.length) {
769
  renderResultFiles(); showResult(Math.min(activeResultIdx, jobResults.length - 1));
770
  }
@@ -784,9 +802,20 @@ async function poll() {
784
  document.getElementById("run-btn").disabled = false;
785
  }
786
  } catch (e) {
787
- setProgress("error", "Erreur de polling", "—");
788
- setStatus("error", "Erreur de polling : " + e.message);
789
- document.getElementById("run-btn").disabled = false;
 
 
 
 
 
 
 
 
 
 
 
790
  }
791
  }
792
 
 
440
  'use strict';
441
 
442
  const POLL_MS = 1000;
443
+ const POLL_MAX_FAILURES = 12; // hoquets transitoires tolérés avant d'abandonner le suivi
444
  let currentJobId = null;
445
  let pollTimer = null;
446
+ let pollFailures = 0;
447
  let activeTab = "exercice";
448
  let loadedFiles = []; // [{filename, content}]
449
  let jobResults = []; // résultats par fichier
 
729
 
730
  if (pollTimer) { clearTimeout(pollTimer); pollTimer = null; }
731
  currentJobId = null;
732
+ pollFailures = 0;
733
  jobResults = []; activeResultIdx = 0;
734
  document.getElementById("run-btn").disabled = true;
735
  hideStatus();
 
762
  async function poll() {
763
  if (!currentJobId) return;
764
  try {
765
+ const res = await fetch(`/api/jobs/${currentJobId}`, { headers: { "Accept": "application/json" } });
766
+ // Lire en texte d'abord : sous forte charge, le proxy HF peut renvoyer une
767
+ // page HTML (502/504) au lieu du JSON → on traite ça comme un hoquet
768
+ // transitoire et on RÉESSAIE, au lieu de tuer tout le suivi.
769
+ const raw = await res.text();
770
+ let data;
771
+ try { data = JSON.parse(raw); }
772
+ catch (_) { throw new Error(`réponse non-JSON (HTTP ${res.status})`); }
773
+
774
+ if (res.status === 404) {
775
+ // Job inconnu : le serveur a probablement redémarré (perte du suivi en mémoire).
776
+ setProgress("error", "Suivi perdu", "—");
777
+ setStatus("error", "Le serveur a perdu ce job (redémarrage). Le traitement est interrompu — relance.");
778
+ document.getElementById("run-btn").disabled = false;
779
+ return;
780
+ }
781
+
782
+ pollFailures = 0; // réponse valide → on repart à zéro
783
  jobResults = data.results || [];
784
  if (data.status === "running") {
785
  setProgress("running", data.step_label || "…", `${data.files_done}/${data.files_total}`);
 
786
  if (jobResults.length && activeResultIdx < jobResults.length) {
787
  renderResultFiles(); showResult(Math.min(activeResultIdx, jobResults.length - 1));
788
  }
 
802
  document.getElementById("run-btn").disabled = false;
803
  }
804
  } catch (e) {
805
+ // Erreur TRANSITOIRE (proxy HF, worker occupé en calcul, réseau) : on
806
+ // réessaie avec un léger backoff. Le job continue côté serveur.
807
+ pollFailures++;
808
+ if (pollFailures >= POLL_MAX_FAILURES) {
809
+ setProgress("error", "Connexion interrompue", "—");
810
+ setStatus("error",
811
+ "Suivi interrompu après plusieurs tentatives (" + e.message + "). "
812
+ + "Le traitement continue peut-être côté serveur : recharge la page dans ~1 min "
813
+ + "pour le retrouver, ou relance avec moins de fichiers à la fois.");
814
+ document.getElementById("run-btn").disabled = false;
815
+ return;
816
+ }
817
+ setStatus("warn", `Reconnexion au suivi… (${pollFailures}/${POLL_MAX_FAILURES})`);
818
+ pollTimer = setTimeout(poll, Math.min(6000, POLL_MS * (1 + pollFailures))); // backoff léger
819
  }
820
  }
821