Skip to content

Fix passing outdated Channel data for CidEvents to ChatEventHandler.handleChatEvent#6385

Open
VelikovPetar wants to merge 1 commit intodevelopfrom
port/v6-to-develop/fix-outdated-channel-data-cid-events
Open

Fix passing outdated Channel data for CidEvents to ChatEventHandler.handleChatEvent#6385
VelikovPetar wants to merge 1 commit intodevelopfrom
port/v6-to-develop/fix-outdated-channel-data-cid-events

Conversation

@VelikovPetar
Copy link
Copy Markdown
Contributor

@VelikovPetar VelikovPetar commented Apr 27, 2026

Goal

Ports V6 commit 1b7caac2a0 ("Fix passing outdated Channel data for CidEvents to the ChatEventHandler.handleChatEvent. (#6381)") to develop.

This was a manual port because the files moved from stream-chat-android-state to stream-chat-android-client on develop.

The fix makes QueryChannelsLogic.parseChatEventResults prefer in-memory per-channel state (already updated by channel event handlers) over stale DB data when resolving channels for CidEvents passed to ChatEventHandler.handleChatEvent.

Implementation

  • QueryChannelsLogic.parseChatEventResults — Instead of always fetching channel data from DB, the method now first checks in-memory per-channel state via StateRegistry. Only channels not currently active in memory fall back to DB lookup.
  • QueryChannelsStateLogic.getActiveChannelState — New method that returns the current Channel snapshot from the in-memory state registry if the channel is active, or null otherwise.
  • Added 3 tests for parseChatEventResults (in-memory only, DB fallback, mixed resolution).
  • Added 2 tests for getActiveChannelState (active → returns channel, inactive → returns null).

UI Changes

No UI changes.

Testing

  • Unit tests cover all three resolution paths: in-memory only, DB fallback, and mixed.
  • getActiveChannelState tested for both active and inactive channels.
  • All existing tests pass. Detekt, spotless, and apiDump verified.

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Enhanced channel state resolution to prioritize in-memory active channels over database lookups when available, reducing unnecessary queries and improving event processing consistency.
  • Tests

    • Added comprehensive unit tests validating channel state resolution behavior for active and inactive channels.

…he `ChatEventHandler.handleChatEvent`.

Co-Authored-By: Claude <noreply@anthropic.com>
@VelikovPetar VelikovPetar added the pr:bug Bug fix label Apr 27, 2026
@VelikovPetar VelikovPetar changed the title Port V6 fix: Fix passing outdated Channel data for CidEvents to ChatEventHandler.handleChatEvent Fix passing outdated Channel data for CidEvents to ChatEventHandler.handleChatEvent Apr 27, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 27, 2026

PR checklist ✅

All required conditions are satisfied:

  • Title length is OK (or ignored by label).
  • At least one pr: label exists.
  • Sections ### Goal, ### Implementation, and ### Testing are filled.

🎉 Great job! This PR is ready for review.

@VelikovPetar VelikovPetar changed the title Fix passing outdated Channel data for CidEvents to ChatEventHandler.handleChatEvent Fix passing outdated Channel data for CidEvents to ChatEventHandler.handleChatEvent Apr 27, 2026
@github-actions
Copy link
Copy Markdown
Contributor

SDK Size Comparison 📏

SDK Before After Difference Status
stream-chat-android-client 5.82 MB 5.82 MB 0.00 MB 🟢
stream-chat-android-ui-components 11.02 MB 11.02 MB 0.00 MB 🟢
stream-chat-android-compose 12.33 MB 12.33 MB 0.00 MB 🟢

@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
70.8% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

@VelikovPetar VelikovPetar marked this pull request as ready for review April 27, 2026 11:09
@VelikovPetar VelikovPetar requested a review from a team as a code owner April 27, 2026 11:09
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 27, 2026

Walkthrough

The changes optimize channel event handling by prioritizing in-memory active channel state lookup over database queries. A new helper method getActiveChannelState retrieves channel snapshots from the in-memory registry when marked active, and parseChatEventResults now uses this to resolve channels, querying the database only for channels not currently active in memory.

Changes

Cohort / File(s) Summary
Channel State Resolution Logic
src/main/java/io/getstream/chat/android/client/internal/state/plugin/logic/querychannels/internal/QueryChannelsLogic.kt, src/main/java/io/getstream/chat/android/client/internal/state/plugin/logic/querychannels/internal/QueryChannelsStateLogic.kt
Added getActiveChannelState helper to fetch in-memory channel snapshots; updated parseChatEventResults to prefer in-memory active state and fallback to database only for missing cids, reducing unnecessary DB queries.
Channel State Resolution Tests
src/test/java/io/getstream/chat/android/client/internal/state/plugin/logic/querychannels/internal/QueryChannelsLogicTest.kt, src/test/java/io/getstream/chat/android/client/internal/state/plugin/logic/querychannels/internal/QueryChannelsStateLogicTest.kt
Added 5 unit tests validating channel resolution behavior: verifying DB lookups are skipped for in-memory active channels, performed for inactive channels, and correctly handling mixed scenarios with proper channel instance passing.

Sequence Diagram(s)

sequenceDiagram
    participant Event as Chat Event
    participant Parser as parseChatEventResults
    participant Registry as State Registry<br/>(In-Memory)
    participant DB as Database
    participant Handler as Event Handler

    Event->>Parser: CidEvent(s)
    
    par For each CID
        Parser->>Registry: getActiveChannelState(cid)<br/>check if active
        alt Channel is Active
            Registry-->>Parser: Channel (from memory)
            Parser->>Handler: handleChatEvent(Channel)
        else Channel Not Active
            Registry-->>Parser: null
            Parser->>DB: selectChannels([cid])
            DB-->>Parser: Channel (from DB)
            Parser->>Handler: handleChatEvent(Channel)
        end
    end
    
    Handler-->>Parser: EventHandlingResult
    Parser-->>Event: Combined Results
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • gpunto

Poem

🐰 In-memory channels hop with glee,
No database queries need to be,
The registry knows which are alive,
DB falls back when needed—how we thrive!
Fast event handling, state so keen,

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main fix: preventing outdated Channel data from being passed to ChatEventHandler by preferring in-memory state over database data for CidEvents.
Description check ✅ Passed The description covers Goal, Implementation, UI Changes, and Testing sections as required by the template. All key sections are populated with sufficient detail about the fix, approach, and test coverage.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 port/v6-to-develop/fix-outdated-channel-data-cid-events

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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
stream-chat-android-client/src/main/java/io/getstream/chat/android/client/internal/state/plugin/logic/querychannels/internal/QueryChannelsStateLogic.kt (1)

247-255: Minor: method name implies a ChannelState but returns Channel.

getActiveChannelState returns a Channel snapshot, not a ChannelState. Consider getActiveChannel (or getActiveChannelSnapshot) for clarity—State in the name suggests the live ChannelState flow. Not a blocker; the implementation is correct and aligns with the existing refreshChannels pattern.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@stream-chat-android-client/src/main/java/io/getstream/chat/android/client/internal/state/plugin/logic/querychannels/internal/QueryChannelsStateLogic.kt`
around lines 247 - 255, The method getActiveChannelState is misnamed because it
returns a Channel snapshot rather than a ChannelState; rename it to
getActiveChannel or getActiveChannelSnapshot for clarity, update its declaration
and all references/usages accordingly (e.g., callers expecting
getActiveChannelState), and ensure documentation/comments reflect that it
returns a Channel snapshot from stateRegistry.channel(type, id).toChannel() and
not a live ChannelState flow.
stream-chat-android-client/src/test/java/io/getstream/chat/android/client/internal/state/plugin/logic/querychannels/internal/QueryChannelsStateLogicTest.kt (1)

154-161: Optional: also assert short-circuit when channel is inactive.

The test verifies the null return value but doesn't confirm that stateRegistry.channel(...) is not invoked when isActiveChannel returns false. Adding a verify(stateRegistry, never()).channel(any(), any()) would lock in the short-circuit guarantee and protect against future regressions where someone might accidentally invert the order of operations.

♻️ Proposed refinement
     `@Test`
     fun `getActiveChannelState should return null when channel is not active in state registry`() {
         whenever(stateRegistry.isActiveChannel(type, id)) doReturn false

         val result = queryChannelsStateLogic.getActiveChannelState(testCid)

         assertNull(result)
+        verify(stateRegistry, never()).channel(any(), any())
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@stream-chat-android-client/src/test/java/io/getstream/chat/android/client/internal/state/plugin/logic/querychannels/internal/QueryChannelsStateLogicTest.kt`
around lines 154 - 161, The test getActiveChannelState should also assert the
short-circuit behavior: after setting
whenever(stateRegistry.isActiveChannel(type, id)) doReturn false and calling
queryChannelsStateLogic.getActiveChannelState(testCid), add a verification that
stateRegistry.channel(...) was never invoked (e.g., verify(stateRegistry,
never()).channel(any(), any())) to ensure getActiveChannelState short-circuits;
reference the methods isActiveChannel, channel, and getActiveChannelState and
the testCid input when adding this assertion.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@stream-chat-android-client/src/main/java/io/getstream/chat/android/client/internal/state/plugin/logic/querychannels/internal/QueryChannelsStateLogic.kt`:
- Around line 247-255: The method getActiveChannelState is misnamed because it
returns a Channel snapshot rather than a ChannelState; rename it to
getActiveChannel or getActiveChannelSnapshot for clarity, update its declaration
and all references/usages accordingly (e.g., callers expecting
getActiveChannelState), and ensure documentation/comments reflect that it
returns a Channel snapshot from stateRegistry.channel(type, id).toChannel() and
not a live ChannelState flow.

In
`@stream-chat-android-client/src/test/java/io/getstream/chat/android/client/internal/state/plugin/logic/querychannels/internal/QueryChannelsStateLogicTest.kt`:
- Around line 154-161: The test getActiveChannelState should also assert the
short-circuit behavior: after setting
whenever(stateRegistry.isActiveChannel(type, id)) doReturn false and calling
queryChannelsStateLogic.getActiveChannelState(testCid), add a verification that
stateRegistry.channel(...) was never invoked (e.g., verify(stateRegistry,
never()).channel(any(), any())) to ensure getActiveChannelState short-circuits;
reference the methods isActiveChannel, channel, and getActiveChannelState and
the testCid input when adding this assertion.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: b3417c0e-d596-406b-aaa9-529ca6d2b277

📥 Commits

Reviewing files that changed from the base of the PR and between 217d159 and 39b6d22.

📒 Files selected for processing (4)
  • stream-chat-android-client/src/main/java/io/getstream/chat/android/client/internal/state/plugin/logic/querychannels/internal/QueryChannelsLogic.kt
  • stream-chat-android-client/src/main/java/io/getstream/chat/android/client/internal/state/plugin/logic/querychannels/internal/QueryChannelsStateLogic.kt
  • stream-chat-android-client/src/test/java/io/getstream/chat/android/client/internal/state/plugin/logic/querychannels/internal/QueryChannelsLogicTest.kt
  • stream-chat-android-client/src/test/java/io/getstream/chat/android/client/internal/state/plugin/logic/querychannels/internal/QueryChannelsStateLogicTest.kt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr:bug Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants