Skip to content

Fix thread detail subscription race#3174

Open
Quicksaver wants to merge 33 commits into
pingdotgg:mainfrom
Quicksaver:fix/thread-detail-subscription-race
Open

Fix thread detail subscription race#3174
Quicksaver wants to merge 33 commits into
pingdotgg:mainfrom
Quicksaver:fix/thread-detail-subscription-race

Conversation

@Quicksaver

@Quicksaver Quicksaver commented Jun 19, 2026

Copy link
Copy Markdown

Summary

Fixes a race in the thread-detail WebSocket subscription path where live events could be emitted while the server was still loading the initial snapshot and snapshot sequence. subscribeThread now attaches its live domain-event subscription before snapshot loading, still emits the loaded snapshot first, then emits only matching thread-detail events newer than the loaded snapshot sequence.

What Changed

  • Exposed OrchestrationEngine.subscribeDomainEvents so callers that need gap-free live observation can acquire a scoped PubSub subscription before starting dependent work, while preserving streamDomainEvents as the existing live stream surface.
  • Added a WebSocket helper that builds a live domain-event stream from the scoped subscription when available, with a fallback to the existing streamDomainEvents implementation for older or test engines.
  • Updated subscribeThread to attach the live stream before loading the thread snapshot and snapshot sequence.
  • Preserved the snapshot-first stream contract by emitting each loaded snapshot first, then draining queued/live events whose sequence is greater than the loaded snapshot sequence.
  • Added a server regression test that delays the initial thread snapshot, emits a live user-message event during that delay, and verifies subscribers receive the snapshot followed by the live event.

Why

This addresses an intermittent first-prompt rendering bug: when sending the first prompt, the first user message could briefly appear in the conversation and then disappear, leaving only the rest of the conversation. In that failure mode, the first visible conversation item could become the Working for... label instead of the user's submitted message.

Validation

  • pnpm exec vp test run apps/server/src/server.test.ts -t "buffers thread detail events emitted while loading the initial thread snapshot" --reporter=dot passed on head 8568992f.
  • pnpm exec vp check passed on head 8568992f, with existing lint warnings outside the PR diff.
  • pnpm exec vp run typecheck passed on head 8568992f, with existing desktop Effect suggestions outside the PR diff.
  • After pushing head 8568992f, GitHub reports the PR is open, mergeable, and approved; CodeRabbit, Vercel, PR Vouch, PR Size, Cursor Bugbot, Macroscope Approvability, Macroscope Correctness, and Macroscope Effect Service Conventions are successful or skipped where appropriate.

Proof

  • No proof files are attached.

Note

Medium Risk
Changes real-time delivery semantics on a core conversation WebSocket path; mistakes could duplicate or omit messages, though new tests target the race.

Overview
Fixes a race where subscribeThread could drop live thread-detail events that arrived while the server was still loading the initial snapshot or finishing persisted catch-up replay.

OrchestrationEngine now exposes subscribeDomainEvents, a scoped PubSub subscription so callers can attach a dedicated live listener before slower work runs. streamDomainEvents is unchanged for existing consumers.

The WebSocket path starts that subscription first, filters to thread-detail events, and drains them into a scoped unbounded queue. After the snapshot (or replay through afterSequence), it emits only events with sequence greater than the loaded/replayed cursor so overlaps are not duplicated.

Regression tests cover delayed snapshot load and replay overlapping with live publishes.

Reviewed by Cursor Bugbot for commit b516f9c. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Fix race condition in subscribeThread WebSocket handler by buffering events during snapshot load

  • The subscribeThread handler in ws.ts previously used a direct stream from orchestrationEngine.streamDomainEvents, which could drop events that arrived while the initial snapshot or catch-up replay was loading.
  • A new subscribeDomainEvents method is added to OrchestrationEngineShape that returns a scoped, independent PubSub subscription per caller.
  • Live thread events are now buffered into an unbounded queue before snapshot/replay begins; the tail stream deduplicates by filtering out events at or below the last snapshot or catch-up sequence number.
  • Two new tests in server.test.ts validate ordered delivery and deduplication for both the initial snapshot and afterSequence replay flows.
  • Behavioral Change: events arriving during snapshot load or catch-up replay are now buffered and replayed rather than dropped, changing delivery semantics for the subscribeThread stream.

Macroscope summarized b516f9c.

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 2fcf3957-67c4-48b5-befa-97119c882a2e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Jun 19, 2026
@macroscopeapp

macroscopeapp Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved

This is a targeted bug fix for a race condition in thread detail subscriptions. The fix acquires the live event subscription and buffers events before loading snapshots, then deduplicates by sequence number. The change is well-tested with two scenarios covering the race conditions, and follows existing patterns in the codebase.

You can customize Macroscope's approvability policy. Learn more.

macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Jun 19, 2026
@Quicksaver

Copy link
Copy Markdown
Author

Comment audit complete: I refreshed the tracked PR comments and found no actionable review feedback. Current comments are informational only: CodeRabbit skipped automated review because reviews are disabled, and Macroscope marked the PR approved. There are no inline review threads to resolve.

@Quicksaver

Copy link
Copy Markdown
Author

Comment audit refreshed: I rechecked the PR issue comments, review comments, and review threads. There is still no actionable review feedback to address. Current comments remain informational only: CodeRabbit skipped automated review because repository reviews are disabled, Macroscope marked the PR approved, and there are no inline review threads to resolve.

@macroscopeapp macroscopeapp Bot dismissed their stale review June 21, 2026 13:02

Dismissing prior approval to re-evaluate 7a1c76d

@github-actions github-actions Bot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Jun 21, 2026

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Effect service review: one convention violation found in the new desktop backend advertisement error. See inline comment.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/desktop/src/backend/DesktopBackendManager.ts Outdated
Comment thread apps/vscode-extension/src/backendManager.ts Outdated
Comment thread apps/vscode-extension/src/extension.ts Outdated
Comment thread apps/web/src/session-logic.ts Outdated
Comment thread apps/web/src/session-logic.ts Outdated
Comment thread apps/vscode-extension/src/webview.ts Outdated
Comment thread apps/web/src/components/ChatView.tsx

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Effect service convention review found 3 issues. See inline comments.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/config.ts Outdated
Comment thread apps/server/src/git/GitWorkflowService.ts Outdated
Comment thread apps/server/src/auth/http.ts Outdated
Comment thread apps/web/src/components/chat/ChatComposer.tsx Outdated
Comment thread apps/web/src/components/chat/MessagesTimeline.tsx
@Quicksaver Quicksaver force-pushed the fix/thread-detail-subscription-race branch from 9e8cc6b to 58463a9 Compare June 26, 2026 06:34
@github-actions github-actions Bot added size:M 30-99 changed lines (additions + deletions). and removed size:XXL 1,000+ changed lines (additions + deletions). labels Jun 26, 2026
macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Jun 26, 2026
- Limit subscription buffering to a scoped bounded queue
- Backpressure slow thread-detail consumers instead of growing memory
@macroscopeapp macroscopeapp Bot dismissed their stale review June 30, 2026 09:58

Dismissing prior approval to re-evaluate 2f3b463

macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Jun 30, 2026
- Buffer live shell events before the initial snapshot resolves
- Drop buffered events already covered by the snapshot sequence
- Add a regression test for the shell subscription race
- Replace replaying test queues with callback streams

- Publish events only after live stream consumption starts
- Acquire domain event subscriptions before loading snapshots

- Cover shell and thread races with PubSub-backed tests
- Derive stream events from scoped subscriptions
- Share orchestration event mocks in server tests
- Cover shell snapshot deduplication
- Add a sliding buffer before websocket stream filtering

- Keep shell and thread subscribers from growing unbounded backlogs
@macroscopeapp macroscopeapp Bot dismissed their stale review July 1, 2026 10:29

Dismissing prior approval to re-evaluate ecffa75

macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Jul 1, 2026
- Replace hot domain-event streams with scoped subscriptions
- Update tests and mocks to publish through PubSub
- Add shared listener helper with failure logging

- Reuse helper across reactors and relay

- Simplify domain event subscription test setup
@macroscopeapp macroscopeapp Bot dismissed their stale review July 3, 2026 13:51

Dismissing prior approval to re-evaluate 8568992

macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Jul 3, 2026
…ubscription-race

# Conflicts:
#	apps/server/src/ws.ts
- Drain the live subscription into a scoped thread-filtered queue
- Resume the post-snapshot tail from the buffered event stream
- Track the highest persisted sequence before draining live events
- Share scoped live buffering and document its non-dropping lifetime
- Cover snapshot filtering and replay overlap in server tests
@macroscopeapp macroscopeapp Bot dismissed their stale review July 11, 2026 10:59

Dismissing prior approval to re-evaluate 414eafb

@github-actions github-actions Bot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Jul 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant