Skip to content

Raise the global event bus ring to 1024 and unify lagged-receiver reporting - #236

Merged
acoliver merged 1 commit into
mainfrom
issue234
Sep 7, 2026
Merged

acoliver merged 1 commit into
mainfrom
issue234

Conversation

@acoliver

@acoliver acoliver commented Sep 5, 2026 •

Copy link
Copy Markdown
Owner

Fixes #234

The global event bus singleton was EventBus::new(16): one tokio broadcast ring of sixteen slots, shared by every subscriber in the process. A receiver that stopped polling while seventeen or more events were emitted got RecvError::Lagged, and the events it missed were evicted for good.

What changed

The ring is sized by a named constant, GLOBAL_BUS_CAPACITY = 1024, whose doc comment states the arithmetic rather than asserting a number: a subscriber resuming after k emitted events receives Lagged(k - capacity), so nothing is lost while a subscriber stays within capacity of the writer.

Receive-error handling moved into one function. handle_recv_error in src/events/bus.rs warns with the component name and skipped count on Lagged and returns whether the loop should keep polling, marked #[must_use] so a caller cannot ignore closure. The ten presenter event loops and the broadcast-to-mpsc view-command bridge in main_gpui.rs all delegate to it.

What this does not claim

The issue as filed said lag was invisible. That was wrong, and I corrected it in a comment on #234 before writing this. All eleven production poll sites already matched RecvError::Lagged and warned with the skipped count. Consolidating them makes the wording uniform and denies a future poll site the chance to omit the warning silently, but it adds no reporting that was missing. The capacity is the substantive fix here; the helper is a refactor.

One consequence worth knowing: every site now emits the helper's wording, "{component} lagged: {n} events skipped and lost", replacing per-site phrasing such as "{} bridge lagged: {} commands dropped". Log greps written against the old strings need updating.

On #231

#231 reports concurrent_streams::cancel_emits_event_only_for_target flaking, and attributes it to a drain loop that stops at Lagged. That mechanism is already fixed: both discard_buffered_events and count_stream_cancelled continue past Lagged today, breaking only on Closed or their deadline.

What survives is that continuing past Lagged does not recover the events Lagged represents. If the StreamCancelled event under test was among those evicted from the sixteen-slot ring, the count comes back zero and the assertion fails for real. Capacity 1024 removes that.

I ran cargo test --lib concurrent_streams fifteen times on this branch and all fifteen passed, but that evidence is weak on its own and I am not closing #231 on it: each run was 7 passed; 1264 filtered out in under a second, and a filtered run has almost none of the competing bus traffic the flake needs. The argument for #231 is the arithmetic, not the sample. Leaving it open to be confirmed by ordinary CI runs over time.

Verification

cargo fmt --all -- --check; the full CI clippy invocation including cognitive_complexity / too_many_lines / too_many_arguments / type_complexity / struct_excessive_bools; cargo test --lib --tests (1977 passed, 0 failed, up from 1975 on main); cargo xtask guard; lizard -C 50 -L 100 -w src/; the 1000-line file gate. No lint suppressions, no new dependencies, no existing test weakened.

The capacity test was written first against the old value of 16, observed failing, then went green at 1024. It builds a local EventBus rather than the global singleton, so it cannot itself be perturbed by other tests sharing the process ring, and it asserts the burst arrives in order, not merely that it arrives.

The STEERING_BUS_LOCK test serialization from #222 is deliberately untouched. It can likely be removed now that the ring is not the constraint, but that is a separate change with its own verification burden.

Summary by CodeRabbit

  • Bug Fixes

    • Improved event delivery during high-volume activity by increasing event buffer capacity and reducing missed updates when processing temporarily falls behind.
    • Event streams now handle temporary backlogs consistently, while cleanly stopping when a stream is no longer available.
  • Tests

    • Added coverage for event-stream error handling and burst delivery to help ensure updates remain complete and ordered.

@coderabbitai

coderabbitai Bot commented Sep 5, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: a07f672f-4a3c-49d8-87c3-c12d13fde8af

📥 Commits

Reviewing files that changed from the base of the PR and between 92b5bc3 and 6ec2be7.

📒 Files selected for processing (14)
  • src/events/bus.rs
  • src/events/global.rs
  • src/events/mod.rs
  • src/main_gpui.rs
  • src/presentation/api_key_manager_presenter.rs
  • src/presentation/chat_presenter.rs
  • src/presentation/codex_auth_presenter.rs
  • src/presentation/error_presenter.rs
  • src/presentation/history_presenter.rs
  • src/presentation/mcp_add_presenter.rs
  • src/presentation/mcp_configure_presenter.rs
  • src/presentation/model_selector_presenter.rs
  • src/presentation/profile_editor_presenter.rs
  • src/presentation/settings_presenter.rs

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The PR raises the global event bus capacity to 1024, adds shared RecvError handling, tests lag classification and burst delivery, and updates event polling loops to use the shared helper.

Changes

Event bus resilience

Layer / File(s) Summary
Shared receive-error contract
src/events/bus.rs, src/events/mod.rs
Adds and re-exports handle_recv_error. The helper logs lagged events, continues polling for Lagged, and stops polling for Closed. Unit tests cover both variants.
Global bus capacity
src/events/global.rs
Defines GLOBAL_BUS_CAPACITY as 1024, uses it to initialize the global bus, and tests ordered delivery during a burst.
Consumer polling updates
src/main_gpui.rs, src/presentation/*_presenter.rs
Updates the bridge and presenter event loops to delegate receive-error handling to handle_recv_error. Removes redundant broadcast imports where applicable.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to d86ba

The global event bus now retains substantially larger bursts for temporarily stalled subscribers while preserving lag reporting and closed-stream behavior. The change is ready to merge with no identified current production risk.

Poem

A rabbit found the bus too small,
So widened rings for events all.
When lagged, it logs and hops along,
When closed, it ends the polling song.
The messages now march in throng.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the two primary changes: increasing the global event bus capacity to 1024 and centralizing lagged-receiver reporting.
Linked Issues check ✅ Passed The changes satisfy issue #234 by raising the global event bus capacity from 16 to 1024 and making receiver lag observable through centralized warning logging with skipped-event counts. The updated ev…
Out of Scope Changes check ✅ Passed The changes remain within the linked issue scope. The shared error handler, presenter updates, re-export, capacity constant, and related tests directly support event-loss prevention and lag reporting.
Docstring Coverage ✅ Passed Docstring coverage is 88.24% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 17 functions across 14 files.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue234

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.

@acoliver

acoliver commented Sep 5, 2026

Copy link
Copy Markdown
Owner Author

The Provider-backed E2E check is red for a reason unrelated to this change: the provider account cannot access the model the test uses.

HTTP 402: {"error":{"message":"this model requires a subscription or extra usage,
upgrade for access at https://ollama.com/upgrade or add extra usage at
https://ollama.com/settings","type":"api_error"}}

The job loads profile ollama / minimax-m2.7:cloud against https://ollama.com/v1, gets 402 on the first attempt, retries once, gets 402 again, and fails after 0.39 seconds. It never reaches any code path this PR touches, and the event log contains nothing but the two HTTP errors.

Every other check passes, including Coverage, both platform build-and-test jobs, the clippy and structural lint gate, formatting, and CodeRabbit.

This will fail the same way on any PR until either the account regains access to minimax-m2.7:cloud or the PA_E2E profile points at a model the account can use. Flagging it rather than rerunning, since a rerun would just spend another macOS runner slot reproducing a 402.

The global event bus singleton was a 16-slot broadcast ring shared by
every subscriber in the process. A receiver that stopped polling while
17 or more events were emitted got RecvError::Lagged and its skipped
events were evicted for good: a stalled UI task lost ChatEvents, and
parallel test runtimes sharing the one ring produced the steering
flakes that commit 1cb981b could only work around by serializing the
tests that observe the bus.

The ring is now sized by the GLOBAL_BUS_CAPACITY constant (1024), so a
subscriber may fall 1024 events behind before anything is evicted. A
deterministic test in src/events/global.rs pins the arithmetic: a burst
larger than the old 16-slot ring but smaller than capacity arrives in
full and in order with no lag.

The eleven production poll sites already reported lag: each of the ten
presenter loops and the view-command bridge in main_gpui.rs matched
RecvError::Lagged and warned with its own wording. That reporting is
now one function, handle_recv_error in src/events/bus.rs, which warns
with the component name and skipped count and returns whether the loop
should keep polling. Consolidating it makes the behaviour uniform and
denies a future poll site the chance to omit the warning silently; it
does not add reporting that was missing. The lag line stays a warning
because the skipped events are already gone when it runs.
@acoliver
acoliver merged commit 44951d6 into main Sep 7, 2026
8 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.

Global EventBus 16-slot ring silently drops events for slow subscribers

1 participant