Spaces:
Runtime error
Runtime error
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- 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
| 788 |
-
|
| 789 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
|