Skip to content

Fix offline persisted drafts not cleared on logout#6379

Merged
VelikovPetar merged 3 commits intodevelopfrom
bug/AND-1150_fix_drafts_not_cleared_on_logout_develop
Apr 21, 2026
Merged

Fix offline persisted drafts not cleared on logout#6379
VelikovPetar merged 3 commits intodevelopfrom
bug/AND-1150_fix_drafts_not_cleared_on_logout_develop

Conversation

@VelikovPetar
Copy link
Copy Markdown
Contributor

@VelikovPetar VelikovPetar commented Apr 20, 2026

Goal

We were not clearing the drafts offline storage on user logout. This resulted in a stuck draft message between sessions.

Ports the #6372 V6 fix to develop

Implementation

Clear the drafts table on logout (same as all other tables)

Testing

  1. Create a draft (enter channel, write a message (don't send), exit channel)
  2. Re-enter same channel and send the message
  3. Logout
  4. Login
  5. The Draft should NOT be present in the channel

Summary by CodeRabbit

  • Bug Fixes
    • Fixed an issue where draft messages were not being cleared when the message repository was cleared, ensuring all message data is properly removed during cleanup operations.

@VelikovPetar VelikovPetar added the pr:bug Bug fix label Apr 20, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 20, 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.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 20, 2026

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
0.0% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

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

coderabbitai Bot commented Apr 20, 2026

Walkthrough

The PR extends the offline message repository's clear() method to also remove persisted draft messages by adding a new deleteAllDrafts() DAO method and invoking it alongside existing deletion operations.

Changes

Cohort / File(s) Summary
Offline Repository Clear Logic
DatabaseMessageRepository.kt, MessageDao.kt
Added deleteAllDrafts() DAO method and integrated it into DatabaseMessageRepository.clear() to ensure draft messages are removed when the repository is cleared.
Test Coverage
MessageRepositoryTests.kt
Added unit test verifying that clear() invokes messageDao.deleteAll(), messageDao.deleteAllDrafts(), and replyMessageDao.deleteAll().

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related PRs

  • PR #6372: Adds the same deleteAllDrafts() method and updates clear() to invoke it for clearing persisted drafts on logout.

Poem

🐰 A rabbit hops through drafts so old,
With whiskers twitching, brave and bold,
Clear the cache, the messages too,
Now drafts all vanish—clean and new! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: clearing drafts on logout, which directly addresses the core issue fixed in the changeset.
Description check ✅ Passed The description includes Goal and Implementation sections explaining the fix clearly, and Testing section with concrete steps. UI Changes and Contributor/Reviewer checklists are omitted but not critical for this bug fix.

✏️ 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-1150_fix_drafts_not_cleared_on_logout_develop

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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
stream-chat-android-client/src/main/java/io/getstream/chat/android/client/internal/offline/repository/domain/message/internal/DatabaseMessageRepository.kt (1)

166-172: ⚠️ Potential issue | 🟡 Minor

Serialize draft insert/delete operations with the same mutex used by clear().

Draft writes at lines 166–172 bypass dbMutex, while clear() (line 263) uses dbMutex.withLock to delete drafts. During logout, userScope.cancelChildren() is called before repositoryFacade.clear(), but cooperative cancellation does not guarantee that in-flight draft saves will be interrupted. A draft write that completes after cancellation is requested but before deleteAllDrafts() executes will survive into the next session. Wrap insertDraftMessage() and deleteDraftMessage() with the same dbMutex as clear() for consistency and safety.

🤖 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/offline/repository/domain/message/internal/DatabaseMessageRepository.kt`
around lines 166 - 172, insertDraftMessage and deleteDraftMessage perform draft
writes without using the same dbMutex used by clear(), which can let drafts
survive logout; wrap both functions' bodies in dbMutex.withLock (the same mutex
used by clear()) so insertDraftMessage (including insertMessage call for
replyMessage and messageDao.insertDraftMessages(message.toEntity())) and
deleteDraftMessage (messageDao.deleteDraftMessage(message.id)) are executed
under the mutex to serialize with clear()/deleteAllDrafts() and prevent race
conditions during cancellation.
🧹 Nitpick comments (1)
stream-chat-android-client/src/test/java/io/getstream/chat/android/client/internal/offline/repository/MessageRepositoryTests.kt (1)

221-240: Add a behavior-level regression for persisted drafts.

This mock test verifies the DAO call, but it would not catch a table/query mismatch or a logout/offline boundary regression. Consider adding a small fake or Room-backed test that inserts a draft, runs the clear/logout path, and asserts selectDraftMessages() is empty. Based on learnings, “Exercise chat flows with provided fakes from stream-chat-android-test and ensure offline ↔ client boundaries are covered.”

🤖 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/offline/repository/MessageRepositoryTests.kt`
around lines 221 - 240, Add a behavior-level regression test that uses a
real/fake Room-backed storage (e.g., provided fakes from
stream-chat-android-test) to persist a draft message, then call
DatabaseMessageRepository.clear() and assert that the persisted drafts are truly
removed by querying the DAO (e.g., selectDraftMessages() returns empty) rather
than only verifying mocks; locate the repository usage in
DatabaseMessageRepository and the DAO methods deleteAllDrafts() /
selectDraftMessages() to implement the integration-style test exercising offline
↔ client logout/clear boundary.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In
`@stream-chat-android-client/src/main/java/io/getstream/chat/android/client/internal/offline/repository/domain/message/internal/DatabaseMessageRepository.kt`:
- Around line 166-172: insertDraftMessage and deleteDraftMessage perform draft
writes without using the same dbMutex used by clear(), which can let drafts
survive logout; wrap both functions' bodies in dbMutex.withLock (the same mutex
used by clear()) so insertDraftMessage (including insertMessage call for
replyMessage and messageDao.insertDraftMessages(message.toEntity())) and
deleteDraftMessage (messageDao.deleteDraftMessage(message.id)) are executed
under the mutex to serialize with clear()/deleteAllDrafts() and prevent race
conditions during cancellation.

---

Nitpick comments:
In
`@stream-chat-android-client/src/test/java/io/getstream/chat/android/client/internal/offline/repository/MessageRepositoryTests.kt`:
- Around line 221-240: Add a behavior-level regression test that uses a
real/fake Room-backed storage (e.g., provided fakes from
stream-chat-android-test) to persist a draft message, then call
DatabaseMessageRepository.clear() and assert that the persisted drafts are truly
removed by querying the DAO (e.g., selectDraftMessages() returns empty) rather
than only verifying mocks; locate the repository usage in
DatabaseMessageRepository and the DAO methods deleteAllDrafts() /
selectDraftMessages() to implement the integration-style test exercising offline
↔ client logout/clear boundary.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: aeedfa05-4deb-45e8-8753-c309a675089a

📥 Commits

Reviewing files that changed from the base of the PR and between d9141e0 and 072504f.

📒 Files selected for processing (3)
  • stream-chat-android-client/src/main/java/io/getstream/chat/android/client/internal/offline/repository/domain/message/internal/DatabaseMessageRepository.kt
  • stream-chat-android-client/src/main/java/io/getstream/chat/android/client/internal/offline/repository/domain/message/internal/MessageDao.kt
  • stream-chat-android-client/src/test/java/io/getstream/chat/android/client/internal/offline/repository/MessageRepositoryTests.kt

@VelikovPetar VelikovPetar merged commit fa66d70 into develop Apr 21, 2026
15 of 16 checks passed
@VelikovPetar VelikovPetar deleted the bug/AND-1150_fix_drafts_not_cleared_on_logout_develop branch April 21, 2026 07:18
@stream-public-bot stream-public-bot added the released Included in a release label Apr 24, 2026
@stream-public-bot
Copy link
Copy Markdown
Contributor

🚀 Available in v7.0.1

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