Repository navigation
fix(relay): read a channel's creation once, not per metadata version - #3244
Merged
Merged
Conversation
Every membership change republishes the channel's kind:39000 to every online member, with a new event id. The background creator-proof read was deduplicated by that id, so each add made every online member issue another kind:9007 query. A run of single-person adds to a large channel multiplied into a relay-wide query burst. A channel's creator and creation receipt never change, so a completed background read is now final for the channel. A failed or limit-cut read still retries on the next version, and strong resolution still revisits proof. Co-authored-by: Elrond <28d6302a099e5225b02c4155ac4236e4912603df2ab08dbfc2f4fef08ce598c8@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Luke Tornquist <[email protected]>
…ttle An empty background answer can be replica lag right after a channel is created. Keep it negative until a metadata version signed CREATION_SETTLE_SECONDS after the channel's creation, which reads once more; a found receipt, or a miss on a settled channel, stays final. Co-authored-by: Elrond <28d6302a099e5225b02c4155ac4236e4912603df2ab08dbfc2f4fef08ce598c8@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Luke Tornquist <[email protected]>
No miss proves a creation absent: a replica can lag at any read, and 39000 created_at is replacement order, not elapsed time. Give every unproved read a negative entry that a later metadata version retries after a jittered backoff on the monotonic clock, doubling from a minute to an hour. A found receipt stays final. Co-authored-by: Elrond <28d6302a099e5225b02c4155ac4236e4912603df2ab08dbfc2f4fef08ce598c8@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Luke Tornquist <[email protected]>
The missing-discovery arm expected a newer live version to re-read the creation at once; reads now back off after a miss. Advance the monotonic clock past the longest jittered backoff first. Classify a cancelled read with the store's isAbort. Co-authored-by: Elrond <28d6302a099e5225b02c4155ac4236e4912603df2ab08dbfc2f4fef08ce598c8@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Luke Tornquist <[email protected]>
TheSentinel454
marked this pull request as ready for review
November 11, 2026 20:44
kazemek21
approved these changes
Nov 11, 2026
kazemek21
left a comment
Contributor
There was a problem hiding this comment.
Kyle reviewed this PR and the Nexus review-tracker notes and approved with no comments.
Posted by Codex (gpt-6.1-sol) on behalf of kylez.
A cancelled read learned nothing, so the next metadata version reads again right away instead of waiting out the miss backoff. Co-authored-by: Elrond <28d6302a099e5225b02c4155ac4236e4912603df2ab08dbfc2f4fef08ce598c8@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Luke Tornquist <[email protected]>
bradseiler
approved these changes
Nov 11, 2026
joahg
added a commit
to joahg/buzz-app
that referenced
this pull request
Nov 12, 2026
* origin/main: (38 commits) Fix reminder counts with compact dock corner tabs (block#3126) Add conditional undo for explicit reads (block#3291) fix(composer): edit channel links as atomic chips (block#3312) fix(agents): show remote instruction limit (block#3325) NEXUS-4033: Offer session skills in the core task composer (block#2790) feat(github): name pasted repository and commit links (block#3268) Let plugins give standing instructions to every agent turn (block#3285) fix(relay): read a channel's creation once, not per metadata version (block#3244) fix(messages): remove unconfirmed sends from this device (block#3317) fix: expose proven non-delivery for artifacts (block#3300) feat(plugins): let plugins mark a person's name in @mention suggestions (block#3260) fix(mcp): strip metadata from images agents attach (block#3311) fix(identity): name a linked key that isn't here, and keep Restore after a failed backup check (block#3238) feat(changesets): show the files a local agent changed on its reply (block#3214) fix(identity): show a backed-up key as backed up, and drop dead retries (block#3223) fix(browser): open Builderlab account connections in the system browser (block#3287) Expose exact captured-message reads (block#3264) docs(agents): keep internal discussion out of public repo content (block#3258) fix(identity): clear a copied private key, name restore failures, fix storage copy (block#3236) fix(channels): list workspaces that load after `#` opens (block#3277) ...
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Each membership change makes the relay republish the channel's kind:39000 metadata, re-signed and so with a new event id, to every online member. Members get it because every joined channel sits in a batched live route over
CHANNEL_KINDS.On each 39000,
applyDiscoverycallsreadCreations. That issues a background kind:9007 read for the channel's creator proof (huddle detection). The read was deduplicated by metadata version, so every republish missed the dedupe. Each single-person add made every online member send another/query.Cost per run of adds: members online × adds. A bulk run of single-person adds to large channels turned this into a relay-wide burst of 9007 reads.
Change
readCreationsnow deduplicates background reads per channel instead of per version. A channel's creator (P) and creation receipt never change.performance.now()). The backoff starts at a minute and doubles to an hour, with jitter up to 1.5×.created_atreflects replacement order, not elapsed time. A Huddle whose receipt was missing therefore still gets classified once the receipt is readable.consistency: "strong") still bypasses the dedupe. Huddle invites resolve this way.Background reads per client per membership change go from 1 to 0 once a channel's proof is found. Until then they are bounded by the backoff rather than by the rate of adds, which also covers a relay that is failing these reads (RPR: design every relay-facing path for the whole fleet at once).
Huddle classification
A Huddle is recognized from its creation receipt. The creator (right after creating) and invitees (on the member-added notice) resolve the room with strong consistency, which bypasses this dedupe and backoff, so the main paths are unchanged.
The difference is only on the background path, when its first read misses the receipt (replica lag or a failed read):
In that window the room shows as an ordinary private channel instead of a Huddle under its parent. Neither version has a timer: with no further version, the room stays unclassified until the next strong resolve or restart, as before.
Rollout
Client-only, no flag: this takes effect as clients upgrade. A relay-side database pool increase is the immediate mitigation for the bursts; this change removes their source.
/queryreads, and database pool wait time during bulk channel adds, before and after the release.What got simpler
CreationReadreplaces its per-version key with a per-channel entry plus a miss count andretryAt. Retries are driven by events, so there are no timers or new lifecycle owners.Tests
New tests in
store.test.ts› creator proof reads drive the live 39000/39002 republish path, with a controlled clock and no jitter.reads a channel's creation once…:
retries a missing creation with backoff until it arrives:
lets the next version read again after a cancelled creation read: a cancelled read issues a new read on the next version without advancing the clock.
Discrimination: the first two fail on base and on the previous revision's store. The cancelled-read test fails if a cancel backs off like a miss.
🤖 Generated with Claude Code
buzz-review-completed