Skip to content

fix(drift): one flush-recovery path, and retries draw only deficient buckets (#106) - #129

Open
schmug wants to merge 2 commits into
mainfrom
claude/project-thread-2520vo-106
Open

schmug wants to merge 2 commits into
mainfrom
claude/project-thread-2520vo-106

Conversation

@schmug

@schmug schmug commented Oct 11, 2026

Copy link
Copy Markdown
Owner

Requested by Schmug · project thread

Before: every refill retry redrew all six buckets against the destructive drawPool, so one bucket that stayed empty drained the five healthy ones on every attempt. When the axis set changed, the flush was repaired two different ways. backgroundFill painted gauges against a null range, while maybeTopUp rebuilt the range on its own and left the old axis labels on screen.

After: a retry draws only the buckets still owed something. A flush is repaired by one routine, whichever refill saw it, and the gauge labels always match the axes the coords were scored against.

How:

  • working-set.js:
    • Each bucket now has a status: ok, failed, empty or pending.
    • A new retry() draws only failed, empty and pending buckets. prime() and topUp() still draw all six.
    • A bucket whose rows all lack coords now counts as empty.
    • A flush marks every bucket pending, because their rows were discarded.
  • drift.js:
    • onFlush only marks the frame stale.
    • Both refills now settle through settleRefill(), which sends a stale frame to one recover(). It runs in the order the issue gives: cancel the fade, refresh the axes and order them by the pool's axisIds, clear current/seen, re-prime the deficient buckets, then frame() (freeze the range, reset position, repaint).
    • enterStage uses the same frame(), and its prime retries now use retry().
    • If a recovery can't finish, the frame stays stale and the background loop retries it on its usual backoff.
  • Extra fix: renderGauges cleared the horizontal container but not the vertical one, so any re-render stacked a second y gauge. Recovery exposed this.

Tests:

  • Four working-set tests:
    • An empty bucket never redrains healthy ones.
    • A failed bucket is retried until it answers.
    • A bucket whose rows lack coords counts as empty.
    • A flush makes every bucket owed again.
  • Three controller tests drive the same flush through the top-up path and the background-fill path. They require identical end state, correct labels, and a redraw of only the buckets the flush emptied.

All seven fail on main.

npm run typecheck is clean. npm test: 895 passing, 0 failing (43 files).

Closes #106

🤖 Generated with Claude Code

https://claude.ai/code/session_01AJidCEAViZHt3GXCmHrurf


Generated by Claude Code

…buckets (#106)

Two refill defects that compounded.

RETRIES REDREW EVERYTHING. Every retry drew all six buckets, against a
destructive drawPool, so one permanently-empty bucket drained the five healthy
ones on every attempt. The working set now keeps a per-bucket status (ok,
failed, empty, pending) and exposes retry(), which draws only the buckets
still owed something. prime() and topUp() still draw all six: the opening pass
and a low-local-supply top-up want the whole spread. A bucket whose rows all
lack coords now counts as empty, since it contributed nothing; a flush marks
every bucket pending, since their rows went with it.

A FLUSH HAD TWO REPAIRS. The flush handler nulled the range, backgroundFill
then painted gauges against null, and maybeTopUp rebuilt the range on its own
while the old axis labels stayed up. Now onFlush only marks the frame stale,
both refills settle through settleRefill(), and a stale frame goes to one
recover(): cancel the fade, refresh axes ordered by the pool's axisIds, clear
current/seen, re-prime the deficient buckets, then frame() (freeze, reset
position, repaint). enterStage uses the same frame(). A recovery that cannot
finish stays stale and the background loop retries it on its backoff.

Also fixes renderGauges, which cleared the horizontal container but not the
vertical one, so any re-render stacked a second y gauge.

Tests: four working-set tests (empty bucket never redrains healthy ones,
failed bucket retried until it answers, coord-less rows count as empty, flush
re-owes every bucket) and three controller tests that drive the same flush
through the top-up path and the background-fill path and require identical
end state. All seven fail on main.

Closes #106

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AJidCEAViZHt3GXCmHrurf
@schmug schmug self-assigned this Oct 11, 2026
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
dewpt c749762 Oct 11 2026, 09:27 PM

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AJidCEAViZHt3GXCmHrurf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Refill: one recovery path, and retry only deficient buckets

2 participants