From e49229c20bff6b3375fc5b934ffb8fbd237fab6b Mon Sep 17 00:00:00 2001 From: giles Date: Thu, 2 Jul 2026 09:34:20 +0000 Subject: [PATCH] otel: sustained SPA poll via a hidden ticker sibling (browser-verified) --- lib/host/otel.sx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/host/otel.sx b/lib/host/otel.sx index 4bc562c0..5fbdfd89 100644 --- a/lib/host/otel.sx +++ b/lib/host/otel.sx @@ -505,12 +505,14 @@ (div :id "otel-dashboard" (h1 "OpenTelemetry") (p :style "font-size:0.8em;opacity:0.7" "live · refreshes every 3s in-app") - ;; STABLE polling element: it fetches GET /otel/fragment every 3s and swaps - ;; its OWN inner content (innerHTML), so #otel-body itself is never removed — - ;; its poll interval keeps firing (an outerHTML self-swap would delete the - ;; polling element after one tick). Boosted → text/sx, so no full reload. - (div :id "otel-body" :sx-get "/otel/fragment" :sx-trigger "every 3s" :sx-swap "innerHTML" - (unquote (otel/-dashboard-body))))))) + ;; HIDDEN POLLER: a sibling that is never itself a swap target, so the swap's + ;; dispose pass never touches it and its poll interval keeps firing. It GETs + ;; /otel/fragment every 3s and swaps the SIBLING #otel-body's inner content. + ;; (Polling the body element itself died after ~2 ticks — the innerHTML swap's + ;; dispose-islands-in disposed the poll's own callback.) + (span :sx-get "/otel/fragment" :sx-trigger "every 3s" :sx-target "#otel-body" + :sx-swap "innerHTML" :style "display:none") + (div :id "otel-body" (unquote (otel/-dashboard-body))))))) ;; ── routes ──────────────────────────────────────────────────────────── ;; Dual-mode, wired into the SPA: a boosted (SX-Request) fetch — a link click OR