Repository navigation
fix(delivery): the failed view counts down, and the retry hints name their condition (#1227) - #1232
Conversation
…s name their condition (#1227) The failure screen froze at "Retrying in 120 s" because the countdown ran once per render and nothing re-rendered between polls; it now redraws once a second while a retry is actually scheduled, and a fresh or loading board starts no timer. The rate-limit and timeout advice said "it retries on its own" without saying who retries; the host installs no timer (#1173), so the sentence now names the condition: while this page is open. Fixes #1227
|
Verdict: PASS at cf9ccff Judged on the tree of 1. The countdown really moves, and only while a retry is scheduled. 2. The hints name their condition. 3. No host timer was added. Ran:
Knives (each on this tip, then restored): Knife 1 — Knife 2 — rate-limit sentence put back to Test 16 also scans Not run: the whole Checks on the tip: 13 success ( Non-blocking: the comment at |
Owner: Dev4 Written-by: Dev4 Reviewer: Reviewer metrics.daily reaches the Delivery header as seven Asia/Shanghai days per countable metric — the four counts plus the CI red share — with a real zero as a filled dot on the baseline and a day nobody could read drawn as a gap instead of a dip to zero. The running day is the one hollow point. A week total keeps a Σ on the counting rows only; a ratio and a median never take one. Rebased onto 00bd382. #1232's countdown and retry hints are kept whole: the failed and stale boards still tick once a second only while a retryAt exists, and the old "It retries on its own (10 s → 30 s → 2 min)." ZH sentence is gone. The client bundle, 0001 and 0008 are regenerated from these sources, and the patches/ds-bot/files/ mirrors are byte-identical to core/.
Fixes #1227
Owner: Dev
Written-by: Dev
Reviewer: Reviewer
Base: 58bd557
Tip SHA: cf9ccff
What changed
The failure screen said
Retrying in 120 sand kept saying it. The number was computed once per render (retryCountdown(payload.retryAt)at render time), and nothing re-rendered between polls, so it froze until the next read — up to two minutes later. It now redraws once a second while a retry is actually scheduled: the timer opens only forfailed/stalewith a finiteretryAt, and it is cleared when the state changes or the view unmounts. Afresh,loading,partialoridleboard starts no timer at all.The second half is wording.
hintForprintedGitHub is rate-limiting this instance; it retries on its own (10 s → 30 s → 2 min).,… it retries on its own in {seconds} s.andGitHub did not answer in time; the next attempt is automatic.— three sentences that do not say who retries. The host installs no timer (the host installs no timer: nothing refreshes behind the browser (#1173)still governscore/src/host/delivery-board.js), so with the page closed nothing retries. They now saywhile this page is open it retries on its own …/the next attempt happens while this page is open …, the generic fallback follows the same rule, and the deadIt retries on its own (10 s → 30 s → 2 min).entry left inZHwas removed. The two board lines that already carried the condition —Retrying in {seconds} s · press Retry to try again nowandWhile this page is open it retries on its own; press Retry to try again now.— are unchanged.No host timer was added.
retryAt,pollDelayand the poller were not touched: this is the screen, not the schedule.Reproduce
On
58bd5575, mountDeliveryBoardwith{ state: 'failed', error, retryAt: now + 120_000 }under a stateful renderer with a fake clock: the first render saysRetrying in 120 s, advancing one second still saysRetrying in 120 s, and there is no timer to advance at all.core/src/client/delivery-view.jshad nosetInterval/requestAnimationFrame, and its onlyuseEffect(insideuseDeliveryBoard) started the poller.For the wording,
hintFor({ kind: 'rate-limit', retryAfterMs: null })on58bd5575returnsGitHub is rate-limiting this instance; it retries on its own (10 s → 30 s → 2 min).— a promise about a background retry that only exists while the page is open.What I ran
node --test test/delivery-view.test.js→ 16/16 pass (14 before, 2 new).delivery-view + delivery-board + i18n + kanban→ 50/50 pass.core/suite on this tip: 1593 tests, 1588 pass, 5 fail — the same five fail on a pristine58bd5575checkout (1591 / 1586 / 5), listed under "Not run".node scripts/build-client.mjs --check→ exit 0 (the bundle in this diff is generated, not hand-edited).node scripts/ds-bot-patches.mjs check:ok ds-bot/ = Fei2411/DeepSeek-Bot@2b10c70 (tree 5834c00, v0.1.5)ok 10 patches apply cleanly in orderok core/ equals ds-bot/ + patches/ds-bot/node scripts/check-arch-docs.mjs→arch-docs: OK (10 changed file(s))(thecore-clientsubsystem page gained one sentence)..github/scripts/check-empty-catch.mjs→ exit 0;check-mojibake.mjs→ok — 0 occurrences of U+FFFD in 1066 text file(s);.github/scripts/changelog.mjs check→3 fragment(s) in changelog.d/ are well formed.Red without the source change
Both knives are on this branch's tree, each with only the wiring removed and then restored (
delivery-view.test.js– 16/16 green again after restore).Knife 1 — delete
const timer = setInterval(() => setNow(Date.now()), 1_000), keep everything else:Knife 2 — put the rate-limit sentence back to
it retries on its own:The second test also scans
src/client/delivery-view.jsandsrc/client/i18n.jsline by line: every line mentioningretries on its ownmust namethis page is open(or页面开着时), so a future sentence cannot quietly drop the condition again.Not run (and why)
The whole
core/suite fails five tests on this tip, and the same five fail on a pristine checkout of58bd5575with the same command — none of them is this change:test/composer-label.test.js,test/header-effects.test.js,test/read-page.test.js—Cannot find module 'jsdom'on this machine.empty diff passesandfixture usage.sqlite has one real calls row with all five fields— fixture/environment failures, identical on both trees.Nothing was run against a live GitHub instance: the countdown and the hint strings are pure client behaviour, and CI's
Node 24job runs the same suite on a machine that hasjsdom.Risk
Small and client-only. The timer is bounded by construction: it only exists while
failed/stalecarries aretryAt, it is cleared on every state change and on unmount, and it callssetNow(Date.now())— no request per tick, so no GitHub reads are added. The one new failure mode would be a re-render loop, which the effect's[ticking, retryAt]dependency rules out: both values come from the payload. The wording change touches only user-visible strings plus theirZHentries, andi18n.test.jsfails if any literal the client translates lacks a Chinese entry.Checkpoint
{ "pr": 1232, "claim": "Dev", "issue": 1227, "summary": "The failed view counts down: while a retry is scheduled the board redraws once a second, and fresh, loading, partial or idle boards start no timer, which is cleared on state change and unmount. The rate-limit and timeout hints now say who retries — while this page is open — because the host installs no timer (#1173). Two new tests mount the component with a fake clock and assert 120 then 119, and scan both client files so no sentence drops the condition again.", "files": [ "core/src/client/delivery-view.js", "core/src/client/i18n.js", "core/test/delivery-view.test.js", "docs/subsystems/core-client.md", "changelog.d/1227-delivery-countdown.fixed.md", "patches/ds-bot/0001-core-fixes.patch", "patches/ds-bot/0008-client-bundle.patch", "core/client.js" ], "checks": { "ran": "delivery-view 16/16; view+board+i18n+kanban 50/50; full core 1593/1588 pass, 5 fail (same 5 on pristine main); build-client --check; ds-bot-patches check 3 ok; arch-docs OK", "result": "green", "at": "cf9ccff3cb91b6f6bf864368d67585de1e0b07aa" }, "next": "Reviewer: judge at cf9ccff3." }