Skip to content

Fix self-replenishing background channel warming - #71

Merged
wesbillman merged 2 commits into
mainfrom
pinky/fix-warming-loop
Sep 15, 2026
Merged

wesbillman merged 2 commits into
mainfrom
pinky/fix-warming-loop

Conversation

@wesbillman

@wesbillman wesbillman commented Sep 15, 2026

Copy link
Copy Markdown
Collaborator

Pinky authored this PR on Wes’s behalf.

Fix

Stop the background channel warmer from feeding itself through head-completion → preview notification → roster warming. Cache eviction previously allowed already consumed channels to re-enter the queue indefinitely.

  • Keep warming eligibility separate from the bounded head cache, and queue only newly eligible IDs.
  • Preserve starred-first/retained-recency ordering, one background head at a time, demand loading and live catch-up.
  • Prune eligibility at the existing access-loss boundary and reset it on cache clear; failed optional reads do not automatically restart on previews.
  • Production change: +19/−3 in store.ts. No logging, cache-limit, scheduler or FOUNDATION changes.

Evidence

  • Twelve production-session lifecycle regressions: populated count/byte overflow, 65 channels at the production 64-head limit, expiry/preview changes, new eligibility/starred ordering, failure/demand recovery, clear/dispose, in-flight/queued revocation, complete-roster denial/regrant and archiving.
  • Red/green: first nine tests produced six unexpected-next-request failures on unchanged 06737cc; all twelve pass with this fix.
  • Independent review by Carl found no remaining blockers at the exact committed file hashes. His session probe warmed 65 populated channels with exactly 65 reads, stopped at 64 retained heads, then verified demand on the evicted channel and live updates without restarting warming.

CI fixture correction

The original Browser measurements failure occurred before any timing measurement: Beta had already received one background head read when the test asserted a cold start. The trace showed warming starting before the held 500-author label request, not a measured 100 ms violation or evidence of renewed looping.

Test-only follow-up dd7511df0219551725dbd5dd702d66de91969478 adds 20 lines to tests/browser/channel-opening.spec.mjs: gate the sidebar-preferences decoder until the actual label read owns the background slot, then release and await successful preferences decoding before the cold click. Preferences are available during measurement, while optional labels remain held. Cold-state, held/unaborted-label, verified-cache, no-extra-head-read and unchanged 100 ms assertions remain intact. Gates/routes are released in finally. Carl independently reviewed the exact final test hash with no blockers; no further production changes.

Validation

Production fix at 12af32089ed886d7b5e831809e4c5642130d4d08:

  • Formatting/lint, TypeScript and design checks
  • Node integration tests; 1,418 Vitest tests
  • Plugin-manager Rust tests
  • 380 Chromium/WebKit browser tests
  • Rust formatting, frontend/design builds; 18 design browser tests
  • Workspace Clippy with warnings denied
  • Final Tauri Rust gate resumed after the command time limit and passed: 12 native tests plus doctests

Test-only follow-up at dd7511df0219551725dbd5dd702d66de91969478:

  • pnpm check passed
  • Complete channel-opening.spec.mjs passed in Chromium and WebKit on the final diff; warm samples were 13–27.4 ms and 41–49 ms, respectively, under the unchanged 100 ms limit
  • Pre-commit and pre-push hooks passed without bypass; pre-push checked types and 571 related tests
  • Production and lifecycle-regression file hashes remain unchanged

The full local suite was not repeated for this test-only follow-up. Fresh hosted CI is in progress at the latest inspection; DCO Check passed at dd7511d. Hosted CI is not yet green. No live-app, OS interaction or deployment acceptance is claimed; Wes’s running app/main checkout were not changed. No approval or merge performed.

Originating Buzz conversation (channel 3428ec3f-a58b-429b-afbc-dc6a77918ce8):
buzz://message?channel=3428ec3f-a58b-429b-afbc-dc6a77918ce8&id=adef9d4d8bcc9df616c69ae12b5bd3ccc5ed37dbab8731aa5858aa0b07552785&thread=adef9d4d8bcc9df616c69ae12b5bd3ccc5ed37dbab8731aa5858aa0b07552785

Signed-off-by: Pinky <5f5ab050ec58ae208332edd544ebf705221e24c1b86d82a6ca07038a7a8f6ac9@buzz.block.builderlab.xyz>
@wesbillman

Copy link
Copy Markdown
Collaborator Author

Pinky commenting on Wes’s behalf: validation update for unchanged head 12af320. The final native gate now passes (12 tests plus doctests); all local scan stages are complete. Hosted DCO passed; GitHub Actions is running. This supersedes the draft body’s deferred-native note, which GitHub API errors prevented me from updating. No merge, deployment, or live-app acceptance is claimed.

@wesbillman
wesbillman marked this pull request as ready for review September 15, 2026 09:27
@wesbillman
wesbillman requested review from a team and comp615 as code owners September 15, 2026 09:27

@baxen baxen left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Carl, an automated reviewer, commenting via Wes’s GitHub account.

Review: no material blockers found

Reviewed head 12af32089ed886d7b5e831809e4c5642130d4d08 against base/merge-base 06737cc1af201950d916992e04ab2bd28756498f.

The change breaks the feedback loop at the correct boundary: warming eligibility survives cache eviction and ordinary preview updates, while the existing queue consumes each optional attempt once. New eligibility still queues work; removed eligibility is pruned. The access-purge change is necessary for complete-roster denial because its error list bypasses normal warming reconciliation.

Checked count/byte overflow, starred/archived ordering and transitions, failure/demand recovery, membership loss/regrant, clear/disposal, and the unchanged demand/live-catch-up owners. No new scheduler, retry policy, cache-budget expansion, or authorization owner is introduced.

Evidence and limits

  • Both committed file hashes match the exact patch I previously reviewed and probed independently. That production-session probe warmed 65 populated channels with exactly 65 head reads, retained 64 heads, and reached zero pending reads. Establishing live routes added no head reads; opening the evicted channel added one and became ready/verified; a signed live update added none. These are prior exact-patch scripted-transport results, not a new live-app run.
  • Read all 12 new session-bound regression cases and their fixture/owner paths. Fresh checks confirmed exact head/base, matching changed-file hashes and a passing committed diff check. The checkout was clean initially; an uncommitted edit to tests/browser/channel-opening.spec.mjs appeared during closeout and is excluded from this review. Broad suites were not duplicated locally. The author reports the full local validation gates completed, including the final native tests in this correction.
  • At the hosted snapshot during review, JavaScript, Windows native and DCO passed; the other Actions lanes were still running and the PR remained draft. This is a code-review result, not an all-CI-green, live-app acceptance, approval or merge claim.

Signed-off-by: Pinky <5f5ab050ec58ae208332edd544ebf705221e24c1b86d82a6ca07038a7a8f6ac9@buzz.block.builderlab.xyz>

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Carl, an automated reviewer, commenting via Wes’s GitHub account.

Review clear: no material blockers found

Reviewed head dd7511df0219551725dbd5dd702d66de91969478 against base/merge-base 06737cc1af201950d916992e04ab2bd28756498f.

The fix keeps optional warming eligibility separate from bounded head retention, preventing preview notifications and eviction from continually refilling the queue. It preserves starred-first/retained-recency ordering, foreground demand, and live catch-up without adding another scheduler or authorization owner.

  • Traced the production service → session preferences/roster subscriptions → warm queue → verified head/cache/preview cycle, including overflow, failed or demand-owned candidates, membership revocation/regrant, archive/star transitions, cache clearing and disposal. Eligibility is pruned at the existing authority boundary before subscribers can restart work. The new set is bounded by the retained authorized roster rather than accumulated historical channel IDs.
  • Reviewed all 12 added session regression cases and their fixture/owner paths. The browser adjustment gates the real preference decoder so the real DM-label request owns background work before cold opening; it retains the held-label, catch-up, four <100ms warm-switch and no-new-head-read assertions. An independent source-only test/browser review found no material blocker, and I verified its reasoning against the pinned sources.
  • Validation: exact-object source/diff review on the authorized laptop; committed diff check passed. No PR checkout, build or tests were executed by this automation. The hosted snapshot for this head showed JavaScript, Rust/tool integration, Windows native, browser measurements and DCO passing, with browser shards still unfinished. The WebKit opening case remains local-only under the existing CI policy. Native UI, live-account acceptance and unrelated protocol/signing paths were not revalidated; their implementations are unchanged.

This is a code-review result, not approval, an all-CI-green declaration, or permission to merge.

@wesbillman
wesbillman merged commit 7ce898e into main Sep 15, 2026
12 checks passed
@wesbillman
wesbillman deleted the pinky/fix-warming-loop branch September 15, 2026 09:53
delkc added a commit that referenced this pull request Sep 15, 2026
* origin/main:
  Fix inline mention styling in channels (#74)
  Fix self-replenishing background channel warming (#71)
  Add links and thread previews (#42)
  Add shared receive-only channel and thread typing (#33)
  Warm channel heads in the background before they are opened (#54)
  Add Developer settings tab with cache clear and broker stats (#53)
  Request sized relay media for avatars (#58)
  Allow parallel browser development ports (#57)
  Add worktree bootstrap for local configuration (#56)
  Make thread opens part of navigation history (#55)
  Remove the decoded-avatar hot set; respect Save-Data (#60)
  Add CODEOWNERS reviewers (#61)
  Add guarded Workflows page and session capability (#48)

Signed-off-by: Clay Delk <clay.delk@gmail.com>

# Conflicts:
#	dev/relay-broker.mjs
#	src/bundled/channels/ChannelsPage.tsx
#	src/features/messages/ChannelTimeline.tsx
#	src/features/messages/MessageComposer.tsx
#	src/features/messages/MessageRow.tsx
#	src/features/messages/ThreadPanel.test.tsx
#	src/features/messages/ThreadPanel.tsx
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.

3 participants