[FIX] script todo: dashboard — stoppe le churn de rendu + nombre de VM
Encore du lag à 16 VM : update_cell était appelé pour CHAQUE ligne à chaque tick (état + « Durée »), or la Durée — dérivée d'un `started` global — est identique sur toutes les lignes et se réécrivait sans cesse -> re-render permanent de la DataTable. - _set_cell : n'appelle update_cell (donc ne re-render) que si la valeur CHANGE. Mesuré : 312 -> 18 update_cell sur 10 ticks × 16 VM. - La durée « live » passe dans le SOUS-TITRE (une seule mise à jour) ; la colonne Durée n'est écrite qu'à la complétion (durée finale figée). - Le NOMBRE de VM est affiché : titre « … (N VM) », sous-titre « k/N terminées · mm:ss ». Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b7522bb92d
commit
fdbec6d19d
2 changed files with 49 additions and 13 deletions
|
|
@ -213,8 +213,24 @@ def run_monitor(manifest_path: str) -> None:
|
|||
self._selected = vms[0]["name"] if vms else None
|
||||
self._follow = True
|
||||
# Statuts TERMINAUX mémorisés : une VM finie n'est plus relue
|
||||
# (réduit fortement l'I/O sur un gros parc).
|
||||
# (réduit fortement l'I/O sur un gros parc). Valeur = (état, code,
|
||||
# durée à la complétion).
|
||||
self._final = {}
|
||||
# Cache des cellules AFFICHÉES : on n'appelle update_cell (donc on
|
||||
# ne re-render) que si la valeur CHANGE -> plus de churn de rendu.
|
||||
self._cells = {}
|
||||
|
||||
@staticmethod
|
||||
def _fmt(secs):
|
||||
mm, ss = divmod(int(secs), 60)
|
||||
return f"{mm:02d}:{ss:02d}"
|
||||
|
||||
def _set_cell(self, table, name, col, value):
|
||||
key = (name, col)
|
||||
if self._cells.get(key) == value:
|
||||
return
|
||||
self._cells[key] = value
|
||||
table.update_cell(name, col, value)
|
||||
|
||||
def compose(self) -> ComposeResult:
|
||||
yield Header(show_clock=True)
|
||||
|
|
@ -236,7 +252,10 @@ def run_monitor(manifest_path: str) -> None:
|
|||
yield Footer()
|
||||
|
||||
def on_mount(self) -> None:
|
||||
self.title = "ERPLibre — suivi d'installation"
|
||||
# Le NOMBRE de VM figure dans le titre ; le sous-titre suit la
|
||||
# progression (terminées / total + durée globale).
|
||||
self.title = f"ERPLibre — {t('install monitoring')} ({len(vms)} VM)"
|
||||
self.sub_title = f"0/{len(vms)} {t('completed')}"
|
||||
self._refresh_ssh()
|
||||
self._load_selected_log(reset=True)
|
||||
# Table toutes les 2 s (30 lectures de fin de log), suivi du log
|
||||
|
|
@ -285,24 +304,33 @@ def run_monitor(manifest_path: str) -> None:
|
|||
# ne doit pas tuer la boucle et figer l'interface.
|
||||
try:
|
||||
table = self.query_one("#vms", DataTable)
|
||||
now = time.time()
|
||||
for vm in vms:
|
||||
name = vm["name"]
|
||||
if name in self._final:
|
||||
continue # déjà terminé -> plus aucune lecture
|
||||
state, code = read_status(vm["log"])
|
||||
label = ICON[state]
|
||||
if state == "failed":
|
||||
label = f"❌ ({code})"
|
||||
elif state == "done":
|
||||
label = "✅"
|
||||
table.update_cell(name, "state", label)
|
||||
if state in ("running", "pending"):
|
||||
mm, ss = divmod(int(time.time() - started), 60)
|
||||
table.update_cell(
|
||||
name, "elapsed", f"{mm:02d}:{ss:02d}"
|
||||
if state in ("done", "failed"):
|
||||
# Fige la durée à la complétion (plus de churn ensuite).
|
||||
elapsed = now - started
|
||||
self._final[name] = (state, code, elapsed)
|
||||
lbl = "✅" if state == "done" else f"❌ ({code})"
|
||||
self._set_cell(table, name, "state", lbl)
|
||||
self._set_cell(
|
||||
table, name, "elapsed", self._fmt(elapsed)
|
||||
)
|
||||
else:
|
||||
self._final[name] = (state, code)
|
||||
# running/pending : icône stable -> _set_cell ne
|
||||
# re-render que si elle change (pas de churn). La durée
|
||||
# « live » est dans le sous-titre, pas répétée 16×.
|
||||
self._set_cell(table, name, "state", ICON[state])
|
||||
# Sous-titre : compteur de VM terminées + durée globale (UNE
|
||||
# seule mise à jour, au lieu de 16 cellules « Durée »).
|
||||
done = len(self._final)
|
||||
self.sub_title = (
|
||||
f"{done}/{len(vms)} {t('completed')} · "
|
||||
f"{self._fmt(now - started)}"
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
|
|
|||
|
|
@ -1278,6 +1278,14 @@ TRANSLATIONS = {
|
|||
"fr": "(inclut des architectures émulées — certaines VM sont lentes)",
|
||||
"en": "(includes emulated architectures — some VMs are slow)",
|
||||
},
|
||||
"install monitoring": {
|
||||
"fr": "suivi d'installation",
|
||||
"en": "install monitoring",
|
||||
},
|
||||
"completed": {
|
||||
"fr": "terminées",
|
||||
"en": "completed",
|
||||
},
|
||||
"Waiting for the VM to start (boot + cloud-init)": {
|
||||
"fr": "En attente du démarrage de la VM (boot + cloud-init)",
|
||||
"en": "Waiting for the VM to start (boot + cloud-init)",
|
||||
|
|
|
|||
Loading…
Reference in a new issue