Skip to content

fix(desktop): stop random timeline message loss + page reconnect replay#1105

Merged
tlongwell-block merged 1 commit into
mainfrom
max/reconnect-replay-unbounded
Jun 18, 2026
Merged

fix(desktop): stop random timeline message loss + page reconnect replay#1105
tlongwell-block merged 1 commit into
mainfrom
max/reconnect-replay-unbounded

Conversation

@tlongwell-block

@tlongwell-block tlongwell-block commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes the reported bug where messages randomly fail to appear in the channel timeline (#buzz-bugs). Root cause was order-dependent eviction in the channel-messages React Query cache; this PR also carries the bounded reconnect-replay paging work.

1. Order-independent timeline cache merge (the bug fix)

The cache had two writers that disagreed on capping:

  • useFetchOlderMessages (scroll-back pager) merged via uncapped sortMessages, growing the array past the 2000 limit.
  • Every live / sync / optimistic writer merged via normalizeTimelineMessages, which ends in slice(-2000).

When a live event arrived while the user was scrolled into deep history, the cap silently evicted the oldest loaded messages — the history they had just paged back to. Whether it fired depended on writer timing, which is why it looked random.

  • Unify the scroll-back pager onto the same normalizer as live/sync via a new mergeTimelineHistoryMessages helper, so all writers leave an identical surviving set regardless of order.
  • Make the 2000-cap content-only: reactions, edits, and tombstones (kind 5/7 and friends) stay in cache so they still apply to retained content, but no longer consume the visible message window. Previously ~1300 tombstones + reactions were eating the window, so the effective message depth was far below 2000.

2. Bounded reconnect replay paging

  • Replace the single reconnect replay REQ with bounded reconnect-replay paging for channel timelines.
  • Reopen the live subscription with its original steady-state filter only; the missed [lastSeen-skew, now] window is owned entirely by 500-event history pages.

Verification

  • bin/pnpm --dir desktop test (985 pass), including:
    • src/features/messages/lib/messageQueryKeys.test.mjs — order-independence regression on a realistic seed (700 current content + 1303 tombstones + 231 reactions + 1500 older + 1 live), asserting both merge orders retain the identical 2000-content set.
    • src/shared/api/relayReconnectReplay.test.mjs — bounded page filters, live/history split, cursor advancement, short-page stop.
  • bin/pnpm --dir desktop check / typecheck / build
  • bin/pnpm --dir desktop exec playwright test --project=smoke tests/e2e/relay-reconnect.spec.ts

Known follow-up (not in this PR)

A user reading very deep history can still lose the top edge when live events arrive, because the 2000-content ceiling is a tail window. A scroll-aware window (don't cap while scrolled up) is filed as a separate enhancement — it's new behavior, not part of this fix.

@tlongwell-block tlongwell-block force-pushed the max/reconnect-replay-unbounded branch from 1f303ab to b6b1328 Compare June 18, 2026 00:57
@tlongwell-block tlongwell-block changed the title fix(desktop): replay missed channel events without limit fix(desktop): page reconnect replay windows Jun 18, 2026
@tlongwell-block tlongwell-block force-pushed the max/reconnect-replay-unbounded branch 2 times, most recently from 1abb7c4 to 64b8960 Compare June 18, 2026 01:24
Co-authored-by: npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@sprout-oss.stage.blox.sqprod.co>
Signed-off-by: npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@sprout-oss.stage.blox.sqprod.co>
@tlongwell-block tlongwell-block force-pushed the max/reconnect-replay-unbounded branch from 64b8960 to b55ff05 Compare June 18, 2026 13:01
@tlongwell-block tlongwell-block changed the title fix(desktop): page reconnect replay windows fix(desktop): stop random timeline message loss + page reconnect replay Jun 18, 2026
@tlongwell-block tlongwell-block merged commit 0181603 into main Jun 18, 2026
25 checks passed
@tlongwell-block tlongwell-block deleted the max/reconnect-replay-unbounded branch June 18, 2026 13:19
tlongwell-block pushed a commit that referenced this pull request Jun 18, 2026
…te-response

* origin/main: (194 commits)
  Fold agent core memory into the session system prompt (#1112)
  feat(cli): add patches and issues commands for NIP-34 git collaboration (#1073)
  fix(desktop): stop random timeline message loss + page reconnect replay (#1105)
  Update README.md
  fix(desktop): keep thread replies from scrolling channel (#1109)
  fix(buzz-acp): accept siblings under allowlist author gate (#1108)
  feat(deploy): add production Helm chart for Buzz (#990)
  fix(desktop): keep MembersSidebar input usable while an add is in flight (#1106)
  chore(release): release version 0.3.25 (#1102)
  fix(desktop): stop dimming deferred message lists (#1104)
  Smooth channel loading: single-surface timeline state machine (#1099)
  feat: surface base + persona system prompts in observer feed (#1103)
  ci: move reminder e2e to a dedicated backend-integration job (#1098)
  fix: give agent-observer sub a replay-capable limit (#1100)
  fix: make managed-agent spawn and teardown portable to Windows (#1097)
  fix(desktop): constrain message timeline width with min-w-0 (#1092)
  feat(desktop): reminders notifications, snooze, overlay, and inbox view mode (#1093)
  feat(prompt): add memory hygiene and hoist universal engineering discipline to base prompt (#1085)
  fix(desktop): correct thread-unread badge flicker, stale clear, phantom count, mention gate, and nested count (#1080)
  Fix mention chip alignment (#1094)
  ...

# Conflicts:
#	crates/buzz-cli/src/commands/workflows.rs
tlongwell-block pushed a commit that referenced this pull request Jun 18, 2026
…te-response

* origin/main: (194 commits)
  Fold agent core memory into the session system prompt (#1112)
  feat(cli): add patches and issues commands for NIP-34 git collaboration (#1073)
  fix(desktop): stop random timeline message loss + page reconnect replay (#1105)
  Update README.md
  fix(desktop): keep thread replies from scrolling channel (#1109)
  fix(buzz-acp): accept siblings under allowlist author gate (#1108)
  feat(deploy): add production Helm chart for Buzz (#990)
  fix(desktop): keep MembersSidebar input usable while an add is in flight (#1106)
  chore(release): release version 0.3.25 (#1102)
  fix(desktop): stop dimming deferred message lists (#1104)
  Smooth channel loading: single-surface timeline state machine (#1099)
  feat: surface base + persona system prompts in observer feed (#1103)
  ci: move reminder e2e to a dedicated backend-integration job (#1098)
  fix: give agent-observer sub a replay-capable limit (#1100)
  fix: make managed-agent spawn and teardown portable to Windows (#1097)
  fix(desktop): constrain message timeline width with min-w-0 (#1092)
  feat(desktop): reminders notifications, snooze, overlay, and inbox view mode (#1093)
  feat(prompt): add memory hygiene and hoist universal engineering discipline to base prompt (#1085)
  fix(desktop): correct thread-unread badge flicker, stale clear, phantom count, mention gate, and nested count (#1080)
  Fix mention chip alignment (#1094)
  ...

Co-authored-by: Tyler Longwell <tlongwell@squareup.com>
Signed-off-by: Tyler Longwell <tlongwell@squareup.com>

# Conflicts:
#	crates/buzz-cli/src/commands/workflows.rs
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