Skip to content

fix(desktop): batch live channel subscriptions and pace reconnect replay under relay rate limits - #5

Merged
joahg merged 1 commit into
mainfrom
joah/batch-live-subscriptions
Aug 4, 2026
Merged

fix(desktop): batch live channel subscriptions and pace reconnect replay under relay rate limits#5
joahg merged 1 commit into
mainfrom
joah/batch-live-subscriptions

Conversation

@joahg

@joahg joahg commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Fixes the rate limiting the dev-mode client has been hitting since the relay's per-pubkey admission control shipped (block#1917, ~2 days ago): 50 EVENT/REQ/COUNT frames per 5 s window (10/sec average) per (tenant, pubkey).

The client opened two REQs per member channel (channel events + mentions) — ~159 REQs on cold start for a 72-channel identity, ~71 for the dev identity. Cold start and every reconnect blew the budget; the reconnect replay then re-blasted all REQs with only 50 ms between batches, re-triggering the limiter and causing the repeated disconnects.

Changes

Batch live subscriptions (useLiveChannelUpdates.ts)

  • Channel-event and mention subscriptions now use multi-channel "#h" filters, 25 channels per REQ (LIVE_SUBSCRIPTION_BATCH_SIZE). REQ count drops from 2N to 2·⌈N/25⌉ — 6 REQs instead of ~144 for 72 channels.
  • The diff-based subscription managers now key by batch instead of channel; an unchanged channel set produces identical batch keys and zero churn.
  • buildChannelMentionFilter / subscribeToChannelMentionEvents accept a channel-ID list.

Attribute h-less events client-side (resolveChannelIdByEventReference)

  • Reactions (kind:7) and deletions (kind:5) carry only an e tag; the relay routes them to #h subscriptions by resolving the target's channel server-side (crates/buzz-core/src/filter.rs). With one channel per subscription the client could inject the known channel (withChannelTagFallback); with batched filters it can't, so the handler now resolves the referenced event in loaded timeline caches instead. Unresolved events are dropped — without a loaded cache the timeline merge was a no-op anyway, and these kinds never hit unread/notification paths.

Pace reconnect replay (relayReconnectReplay.ts)

  • REPLAY_INTER_BATCH_DELAY_MS 50 ms → 1000 ms: 8 REQs/sec stays under the relay's 10/sec average with headroom for concurrent publishes.
  • shouldPageReconnectReplay now accepts multi-channel #h filters so batched subscriptions keep paged history replay.

Validation

  • pnpm typecheck clean
  • pnpm test: 4055/4055 pass, including new tests for batchChannelIds, resolveChannelIdByEventReference, and multi-channel paging eligibility

Linear: AGNTOPS-418

The relay's admission control (block#1917) counts EVENT/REQ/COUNT
frames per pubkey at 50 per 5s window. The client opened two REQs per
member channel (~159 for a 72-channel identity), so cold start and
reconnect blew the budget, got the connection rate limited, and replay
re-triggered the limiter on every reconnect.

- Batch live channel-event and mention subscriptions into multi-channel
  "#h" filters, 25 channels per REQ (2N REQs -> ~2*ceil(N/25)).
- Resolve h-less reactions/deletions to their channel via the referenced
  event in loaded timeline caches, mirroring the relay's server-side
  channel resolution (replaces the per-channel withChannelTagFallback).
- Allow reconnect history paging for multi-channel "#h" filters.
- Raise REPLAY_INTER_BATCH_DELAY_MS 50ms -> 1000ms so replay stays at
  8 REQs/sec, under the relay's 10/sec average budget.

AGNTOPS-418

Buzz-Message: buzz://message?channel=0c02d73d-f174-4c5f-99a3-cf67ea3d456f&id=19db0642f1adf65a15c7db646a06f0722d11bf3501bd84c78e8916fd0176b9f7
Amp-Thread-ID: https://ampcode.com/threads/T-019fca69-36c1-71d8-b85d-4099ffea48f1
Co-authored-by: Amp <amp@ampcode.com>
Signed-off-by: Joah Gerstenberg <joah@squareup.com>
@joahg
joahg marked this pull request as ready for review August 4, 2026 14:54
@joahg
joahg merged commit 902bfd6 into main Aug 4, 2026
15 of 21 checks passed
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.

1 participant