refactor(llc): extract channel event handling into handler and state mutations - #2911
Conversation
Replace the three hand-rolled parentId/showInChannel checks with a single private _isShownInChannel helper. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Move the event listener bodies out of ChannelClientState into a ChannelEventHandler dispatching from a single subscription, preserving the original per-subscription execution order. The state class keeps its mutation surface unchanged; the few paths the listeners reached through private state (typing events, watcher removal, member refresh, user message deletion) are injected into the handler as tear-offs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ions Reduce ChannelEventHandler to payload guards and dispatch, moving the state-write logic into a new ChannelStateMutations owning one semantic mutation method per event. Cover the routing and the mutations with dedicated unit tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Drop the references to the pre-refactor listener wiring and the rationale paragraphs; document what each class and method does. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rage' into refactor/extract-channel-event-handler
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## test/channel-event-handling-coverage #2911 +/- ##
========================================================================
+ Coverage 74.55% 74.57% +0.02%
========================================================================
Files 435 437 +2
Lines 28160 28189 +29
========================================================================
+ Hits 20994 21023 +29
Misses 7166 7166 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Submit a pull request
Linear: FLU-723
Github Issue: #
CLA
Description of the pull request
Moves the channel event handling out of
ChannelClientStateinto two new internal classes, with no public API or behavior changes:ChannelEventHandler— validates and routes each WS event from a single subscription (replacing the 36 per-event subscriptions), preserving the original per-subscription execution order via a three-block dispatch. Also owns the side effects an event triggers outside the channel state: member refresh on ban/unban, persisted-message cleanup on truncation, and delivery reconciliation.ChannelStateMutations— owns the state writes, one semantic method per event (onMemberRemoved,onPollVoteCasted, …). The few writes that previously went through private state (typing events, watcher removal, member refresh, user message deletion) stay private onChannelClientStateand are injected as tear-offs, so the state class gains no new members.Why these classes exist
Previously, every event listener interleaved three unrelated responsibilities: deciding whether an event applies (payload/identity/cid guards), computing the resulting state (list surgery, poll merges, unread math), and performing side effects (persistence, delivery reconciliation, member re-fetch). A backend payload change and a state-logic change would land in the same method, and none of it could be tested without a full channel lifecycle.
The split separates those along the same lines as the feeds SDK (our newest state architecture — thin event handlers that guard and route, with all mutation logic owned by semantic methods on the state side):
How this flows into v11
This is the largest subset of the v11 channel refactor achievable without breaking changes, and each piece maps forward:
ChannelStateMutationsis the embryonic write side of v11's read-only/mutable state split — its method list is the mutation contract the mutable state owner needs, discovered and test-pinned now. The five tear-offs mark, by name, exactly which writes must become first-class members of it.ChannelEventHandleris the embryonic event-bus subscriber. The three-block string-typed dispatch exists only to preserve the legacy subscription order; with v11's sealed domain events, the payload guards migrate into the typed event mapping and the ordering constraint can be consciously re-evaluated.Message,Poll+PollVote, …), not raw events, so routing API responses through the same semantic methods — feeds' single-write-path design, the structural fix for the WS-vs-API dual-write races — only needs new plumbing, not another logic move.Net effect: v11's breaking release is left with visibility moves (hiding mutators, exposing read-only state, file split) instead of logic untangling.
Commits are structured for review: the shown-in-channel predicate extraction, the handler extraction, the handler/mutations split, and doc/changelog updates.
Testing: the event coverage added in #2905 (written against the old implementation) passes unchanged against the new one; this PR adds dedicated unit tests for the handler (60 — routing, guards, delegation) and the mutations (53 — state-write logic). Known latent issues are deliberately preserved, not fixed (e.g.
member.addednot deduping, the unguardedlastReadAt!innotification.mark_unread).Screenshots / Videos
No UI changes.