Skip to content

perf(llc, core): guard channel list event handlers against unnecessary re-sorts#2824

Open
VelikovPetar wants to merge 3 commits into
masterfrom
perf/FLU-599_guard_channel_list_event_handlers
Open

perf(llc, core): guard channel list event handlers against unnecessary re-sorts#2824
VelikovPetar wants to merge 3 commits into
masterfrom
perf/FLU-599_guard_channel_list_event_handlers

Conversation

@VelikovPetar

@VelikovPetar VelikovPetar commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Submit a pull request

Linear: FLU-599

Github Issue: #

CLA

  • I have signed the Stream CLA (required).
  • The code changes follow best practices
  • Code changes are tested (add some information if not applicable)

Description of the pull request

Three event handlers in StreamChannelListController unconditionally replaced the entire channel list on every matching event, forcing a full list copy + O(n log n) re-sort even when the event didn't affect any listed channel. This adds a guard to each (matching the one already present in onNotificationRemovedFromChannel):

  • onChannelUpdated / onMemberUpdated — early-return unless the event's channel (event.cid ?? event.channel?.cid) is in the current list.
  • onUserPresenceChanged — member-state updates are preserved exactly; the list is only reassigned (re-sorted) when at least one listed channel actually contained the event user.

Also extracts the previously hard-coded 'user.presence.changed' dispatch string into a new EventType.userPresenceChanged constant.

Breaking change

None — not source-breaking. No public signatures change; this is a behavior-preserving micro-optimization. The old "reassign an unchanged list" path was already a no-op at the UI level (suppressed by PagedValue's DeepCollectionEquality-based == short-circuit in ValueNotifier); the guards only skip the wasted sort + allocation.

Performance

Throwaway micro-benchmark (not committed; the "old" numbers were produced by git stash-ing the real handler, not a copied class), 20k iterations over 30 channels:

Scenario Before After Speedup
channel.updated (out-of-list) 103.2 ms 6.4 ms 16.1×
user.presence.changed (non-member) 163.5 ms 61.1 ms 2.7×

The presence win is smaller by design: presence events carry no cid, so the handler still scans every channel's members; the guard only saves the copy + re-sort on top of that scan.

Tests

  • New stream_channel_list_event_handler_test.dart — unit-tests the handler in isolation against a mock controller, covering every handler method (and the three guards' listed/unlisted/non-member branches).
  • stream_channel_list_controller_test.dart — the Event handling group was rewritten from behavior-assertions into a routing test (mock handler injected) that verifies each event type dispatches to the correct method.
  • Added MockStreamChannelListController and MockStreamChannelListEventHandler.
  • Manual smoke test passed: channel-list presence indicators and reordering verified in the sample app.

Screenshots / Videos

No UI changes.

Summary by CodeRabbit

  • New Features

    • Added a new user.presence.changed event type and integrated it into channel list presence handling.
  • Bug Fixes

    • Improved channel list update behavior so channel.updated, member.updated, and user/presence updates only refresh/re-sort when they affect channels already in the list.
    • Made user presence updates become no-ops when the user isn’t present in any relevant listed channel.
  • Tests

    • Expanded and refocused channel list event handling coverage, including new unit tests and updated mocks.

…y re-sorts

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d23ecdb5-23ad-4e15-a788-544a58fa8efb

📥 Commits

Reviewing files that changed from the base of the PR and between fca8b39 and 6e624ea.

📒 Files selected for processing (1)
  • packages/stream_chat_flutter_core/lib/src/stream_channel_list_event_handler.dart
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/stream_chat_flutter_core/lib/src/stream_channel_list_event_handler.dart

📝 Walkthrough

Walkthrough

Adds a presence event constant, uses it in channel-list event routing, guards updates for unlisted channels or users, and expands routing and handler tests.

Changes

Channel list event handling

Layer / File(s) Summary
Presence event contract and routing
packages/stream_chat/lib/src/event_type.dart, packages/stream_chat/CHANGELOG.md, packages/stream_chat_flutter_core/lib/src/stream_channel_list_controller.dart, packages/stream_chat_flutter_core/CHANGELOG.md
Adds EventType.userPresenceChanged and uses it when routing presence and user update events.
Guarded channel list updates
packages/stream_chat_flutter_core/lib/src/stream_channel_list_event_handler.dart
Only reassigns or re-sorts the channel list when channel or member updates target listed channels, or presence updates affect a listed channel.
Routing and handler validation
packages/stream_chat_flutter_core/test/mocks.dart, packages/stream_chat_flutter_core/test/stream_channel_list_controller_test.dart, packages/stream_chat_flutter_core/test/stream_channel_list_event_handler_test.dart
Adds mocks and tests for event dispatch and channel handler behavior across channel, message, notification, connection, and presence events.

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

Suggested reviewers: xsahil03x

🚥 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 It accurately summarizes the main optimization: guarding channel list event handlers to avoid unnecessary re-sorts.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf/FLU-599_guard_channel_list_event_handlers

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.

@VelikovPetar
VelikovPetar marked this pull request as ready for review July 17, 2026 14:28

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@packages/stream_chat_flutter_core/lib/src/stream_channel_list_event_handler.dart`:
- Around line 191-197: Update the user presence/update handler to treat a
channel as matching when the event user appears in either state.members or
state.membership, so membership-only channels still receive the update and list
re-sort. Add a regression test covering an event user present only in
membership.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3e268090-bafc-4071-b7c8-d55df1a0caf3

📥 Commits

Reviewing files that changed from the base of the PR and between 5f7f33c and 0b28ee2.

📒 Files selected for processing (8)
  • packages/stream_chat/CHANGELOG.md
  • packages/stream_chat/lib/src/event_type.dart
  • packages/stream_chat_flutter_core/CHANGELOG.md
  • packages/stream_chat_flutter_core/lib/src/stream_channel_list_controller.dart
  • packages/stream_chat_flutter_core/lib/src/stream_channel_list_event_handler.dart
  • packages/stream_chat_flutter_core/test/mocks.dart
  • packages/stream_chat_flutter_core/test/stream_channel_list_controller_test.dart
  • packages/stream_chat_flutter_core/test/stream_channel_list_event_handler_test.dart

Comment thread packages/stream_chat_flutter_core/lib/src/stream_channel_list_event_handler.dart Outdated
@codecov

codecov Bot commented Jul 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 71.33%. Comparing base (5f7f33c) to head (6e624ea).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2824      +/-   ##
==========================================
+ Coverage   71.28%   71.33%   +0.05%     
==========================================
  Files         430      430              
  Lines       26934    26940       +6     
==========================================
+ Hits        19199    19218      +19     
+ Misses       7735     7722      -13     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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.

2 participants