Agent: fix Status freeze — conchint.textContent destroyed #capn (root cause) #184

Merged
bvandeusen merged 1 commits from dev into main 2026-07-01 20:46:29 -04:00
+6 -3
View File
@@ -21,7 +21,7 @@ log = logging.getLogger("fc_agent.app")
# Bump on every agent change. The page embeds this and /status reports it; the UI # Bump on every agent change. The page embeds this and /status reports it; the UI
# warns to reload when they differ — so a stale browser-cached page can't be # warns to reload when they differ — so a stale browser-cached page can't be
# mistaken for "the new image didn't deploy". (Belt-and-braces with no-store.) # mistaken for "the new image didn't deploy". (Belt-and-braces with no-store.)
VERSION = "2026-07-01.9 · server-computed jobs/min + downloads/min (poll-rate independent)" VERSION = "2026-07-01.10 · fix Status freeze (conchint.textContent destroyed #capn)"
logbuf.install() logbuf.install()
cfg = Config.from_env() cfg = Config.from_env()
@@ -217,7 +217,7 @@ _PAGE = """<!doctype html><html><head><meta charset=utf-8>
<button class=step onclick=setc(1)>+</button> <button class=step onclick=setc(1)>+</button>
</div> </div>
</div> </div>
<div class=hint id=conchint>auto-tuning downloaders to keep the GPU fed · max <b id=capn>8</b></div> <div class=hint id=conchint>auto-tuning downloaders to keep the GPU fed · max 8</div>
</section> </section>
<section class=card> <section class=card>
@@ -286,7 +286,10 @@ _PAGE = """<!doctype html><html><head><meta charset=utf-8>
applyStatus(s) applyStatus(s)
} }
function applyStatus(s){ function applyStatus(s){
CAP=s.max_concurrency||8; capn.textContent=CAP // NB: don't write a separate `capn` element here — conchint.textContent below
// rewrites the whole hint (incl. the max), and any child element nested in it
// would be destroyed by that write, breaking the NEXT applyStatus call.
CAP=s.max_concurrency||8
// The backend owns the state now (stopped|starting|running|stopping) and drives // The backend owns the state now (stopped|starting|running|stopping) and drives
// every transition, so the pill is always truthful — no client-side guessing // every transition, so the pill is always truthful — no client-side guessing
// from active>0, which used to wedge on "stopping" forever. // from active>0, which used to wedge on "stopping" forever.