host/engine: visible error/retry state for failed fetches + retry on network failure
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 30s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 30s
Two engine fixes in web/orchestration.sx (rebuilt into the WASM bytecode) plus the blog CSS that surfaces them. 1. Retry on NETWORK failure, not just HTTP errors. The fetch error/catch path (the real offline / DNS / connection-refused case) previously dispatched sx:requestError and stopped — only a non-ok HTTP response with an empty body ever reached handle-retry. So "no connection" never recovered. Now the catch path calls handle-retry too, so an sx-retry element actually self-heals when the connection returns (the cap bounds the backoff interval, not the attempt count — it retries forever). 2. Visible failure state. On any failed/aborted fetch the engine adds an `.sx-error` class to the element (cleared, with the retry backoff reset, on the next success). Without it a stuck retry loop is invisible — the picker just sits "Loading…". The blog shell ships CSS so the relate picker shows "Connection problem — retrying…" / "offline, retrying…" on .sx-error. Platform-wide: any sx-get/sx-post element benefits, not just the picker. Tests: relate-picker.spec.js gains a 6th case — abort relate-options, assert .sx-error appears, un-abort, assert it clears and the picker repopulates (proving the retry loop is live). 6/6 browser + 272/272 conformance. WASM web stack rebuilt (orchestration.sxbc + the static hs-* copies refreshed by the same build). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1358,7 +1358,17 @@
|
||||
cls
|
||||
(first extra-classes)
|
||||
tgt))
|
||||
((match-kw "for")
|
||||
((and
|
||||
(= (tp-type) "keyword") (= (tp-val) "for")
|
||||
;; Only consume 'for' as a duration clause if the next
|
||||
;; token is NOT '<ident> in ...' — that pattern is a
|
||||
;; for-in loop, not a toggle duration.
|
||||
(not
|
||||
(and
|
||||
(> (len tokens) (+ p 2))
|
||||
(= (get (nth tokens (+ p 1)) "type") "ident")
|
||||
(= (get (nth tokens (+ p 2)) "value") "in")))
|
||||
(do (adv!) true))
|
||||
(let
|
||||
((dur (parse-expr)))
|
||||
(list (quote toggle-class-for) cls tgt dur)))
|
||||
@@ -3090,7 +3100,17 @@
|
||||
(= (tp-val) "queue"))
|
||||
(do (adv!) (adv!)))
|
||||
(let
|
||||
((every? (match-kw "every")))
|
||||
((every? (match-kw "every"))
|
||||
(throttle-ms nil)
|
||||
(debounce-ms nil))
|
||||
;; 'throttled at <duration>' / 'debounced at <duration>'
|
||||
;; — parsed as handler modifiers, captured as :throttle / :debounce parts.
|
||||
(when (and (= (tp-type) "ident") (= (tp-val) "throttled"))
|
||||
(adv!)
|
||||
(when (match-kw "at") (set! throttle-ms (parse-expr))))
|
||||
(when (and (= (tp-type) "ident") (= (tp-val) "debounced"))
|
||||
(adv!)
|
||||
(when (match-kw "at") (set! debounce-ms (parse-expr))))
|
||||
(let
|
||||
((having (if (or h-margin h-threshold) (dict "margin" h-margin "threshold" h-threshold) nil)))
|
||||
(let
|
||||
@@ -3105,6 +3125,10 @@
|
||||
(match-kw "end")
|
||||
(let
|
||||
((parts (list (quote on) event-name)))
|
||||
(let
|
||||
((parts (if throttle-ms (append parts (list :throttle throttle-ms)) parts)))
|
||||
(let
|
||||
((parts (if debounce-ms (append parts (list :debounce debounce-ms)) parts)))
|
||||
(let
|
||||
((parts (if every? (append parts (list :every true)) parts)))
|
||||
(let
|
||||
@@ -3127,7 +3151,7 @@
|
||||
((parts (if finally-clause (append parts (list :finally finally-clause)) parts)))
|
||||
(let
|
||||
((parts (append parts (list (if (> (len event-vars) 0) (cons (quote do) (append (map (fn (nm) (list (quote ref) nm)) event-vars) (if (and (list? body) (= (first body) (quote do))) (rest body) (list body)))) body)))))
|
||||
parts))))))))))))))))))))))))))
|
||||
parts))))))))))))))))))))))))))))
|
||||
(define
|
||||
parse-init-feat
|
||||
(fn
|
||||
@@ -3177,6 +3201,7 @@
|
||||
(or
|
||||
(= (tp-type) "hat")
|
||||
(= (tp-type) "local")
|
||||
(= (tp-type) "attr")
|
||||
(and (= (tp-type) "keyword") (= (tp-val) "dom")))
|
||||
(let
|
||||
((expr (parse-expr)))
|
||||
|
||||
Reference in New Issue
Block a user