Skip to content

Prevent calling MarkRead on the current user's own unsynced last message#6431

Merged
VelikovPetar merged 1 commit into
v6from
bug/AND-1173_prevent_calling_mark_read_on_own_unsynced_messages
May 12, 2026
Merged

Prevent calling MarkRead on the current user's own unsynced last message#6431
VelikovPetar merged 1 commit into
v6from
bug/AND-1173_prevent_calling_mark_read_on_own_unsynced_messages

Conversation

@VelikovPetar
Copy link
Copy Markdown
Contributor

@VelikovPetar VelikovPetar commented May 11, 2026

Goal

AND-1173 — In an otherwise-empty channel, sending a message while it is still in-flight (optimistic, SyncStatus.IN_PROGRESS) and calling markLastMessageRead causes the server to persist last_read_message_id = "". From the server's perspective the channel is empty at that moment, so it has no message to anchor the read state to. This can causes issues in integrations where they expect a valid last_read_message_id value.

Implementation

In MessageListController.markLastMessageRead(), gate the markRead call on the bottom message: if it is authored by the current user and its syncStatus != COMPLETED, log and return early instead of issuing the API call. Peer messages are not affected — syncStatus is a local-only field and peer messages keep the data-class default, so the gate is intentionally scoped to messages owned by the current user.

UI Changes

No UI changes.

Testing

Unit tests added in MessageListControllerTests:

  • When current user's last message is COMPLETED markLastMessageRead should invoke markRead — happy path, lastSeenMessageId is updated.
  • When current user's last message is not COMPLETED markLastMessageRead should not invoke markRead — gated path, no API call, lastSeenMessageId stays null.
  • When peer's last message is not COMPLETED markLastMessageRead should still invoke markRead — guards against the gate over-matching peer messages that carry the default syncStatus.

The existing When repetitive markLastMessageRead calls appear only single API call should be sent test was updated to seed messages with SyncStatus.COMPLETED so it continues to exercise the dedupe path rather than the new gate.

Manual repro: open an empty channel as a user with no prior reads, send a message, observe markRead request in logs / on the backend before vs. after this fix.

Summary by CodeRabbit

  • Bug Fixes
    • Fixed an issue where the app would prematurely mark unsynced messages as read, causing incorrect read receipts for messages still being sent.

Review Change Stack

Co-Authored-By: Claude <noreply@anthropic.com>
@VelikovPetar VelikovPetar added the pr:bug Bug fix label May 11, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 11, 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 (or ignored for dependabot PRs).

🎉 Great job! This PR is ready for review.

@VelikovPetar VelikovPetar changed the title Prevent markRead on the current user's own unsynced last message Prevent calling MarkRead on the current user's own unsynced last message May 11, 2026
@github-actions
Copy link
Copy Markdown
Contributor

SDK Size Comparison 📏

SDK Before After Difference Status
stream-chat-android-client 5.26 MB 5.26 MB 0.00 MB 🟢
stream-chat-android-offline 5.49 MB 5.49 MB 0.00 MB 🟢
stream-chat-android-ui-components 10.64 MB 10.65 MB 0.00 MB 🟢
stream-chat-android-compose 12.87 MB 12.87 MB 0.00 MB 🟢

@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

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

See analysis details on SonarQube Cloud

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

coderabbitai Bot commented May 11, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 5289eda0-2493-4d3a-ba7d-6ae68a0e5b7c

📥 Commits

Reviewing files that changed from the base of the PR and between 7ad0cda and acf0791.

📒 Files selected for processing (2)
  • stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/feature/messages/list/MessageListController.kt
  • stream-chat-android-ui-common/src/test/kotlin/io/getstream/chat/android/ui/common/feature/messages/list/MessageListControllerTests.kt

Walkthrough

The PR adds sync-status gating to MessageListController.markLastMessageRead(). When the last message is authored by the current user and has syncStatus other than COMPLETED, the controller now skips marking it as read. Tests validate the behavior for synced own messages, unsynced own messages, and unsynced peer messages.

Changes

Sync-Status Read Guard

Layer / File(s) Summary
Import SyncStatus Type
stream-chat-android-ui-common/src/main/kotlin/.../MessageListController.kt, stream-chat-android-ui-common/src/test/kotlin/.../MessageListControllerTests.kt
Add SyncStatus import to support sync-state checks in production and test code.
Core Logic: Gate Read Marking on Sync Status
stream-chat-android-ui-common/src/main/kotlin/.../MessageListController.kt
markLastMessageReadInternal extracts the last message and returns early if it is authored by the current user and syncStatus != SyncStatus.COMPLETED.
Test Helper: Support Sync Status Parameterization
stream-chat-android-ui-common/src/test/kotlin/.../MessageListControllerTests.kt
nowMessage() helper extended to accept optional syncStatus parameter (defaults to SyncStatus.COMPLETED) and forward to randomMessage().
Test Data: Fix Existing Test Fixtures
stream-chat-android-ui-common/src/test/kotlin/.../MessageListControllerTests.kt
Repetitive markLastMessageRead test messages updated to explicitly set syncStatus = SyncStatus.COMPLETED.
Test Coverage: Verify Sync-Status Gating
stream-chat-android-ui-common/src/test/kotlin/.../MessageListControllerTests.kt
Three tests verify: own message with COMPLETED triggers markRead, own message with IN_PROGRESS blocks markRead, and peer message with IN_PROGRESS still triggers markRead.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 A sync-check hops through our queue,
Stopping early when messages aren't through—
No premature reads for work in flight,
Just gentle patience till sync is right. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% 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 and specifically describes the main change: preventing MarkRead calls on unsynced messages from the current user.
Description check ✅ Passed The description covers Goal, Implementation, Testing, and includes UI Changes (none) and manual repro steps. Some optional sections like screenshots, videos, and contributor checklist are incomplete, but core required information is present.
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 bug/AND-1173_prevent_calling_mark_read_on_own_unsynced_messages

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.

@VelikovPetar VelikovPetar merged commit 536a525 into v6 May 12, 2026
18 of 20 checks passed
@VelikovPetar VelikovPetar deleted the bug/AND-1173_prevent_calling_mark_read_on_own_unsynced_messages branch May 12, 2026 07:45
@stream-public-bot stream-public-bot added the released Included in a release label May 12, 2026
@stream-public-bot
Copy link
Copy Markdown
Contributor

🚀 Available in v6.37.4

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

Labels

pr:bug Bug fix released Included in a release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants