Skip to content

fix(chat): skip insurance requests while the chat is paused - #6842

Merged
mahibi merged 2 commits into
nextcloud:masterfrom
ToteMeiSter:fix/chat-insurance-pause
Oct 15, 2026
Merged

mahibi merged 2 commits into
nextcloud:masterfrom
ToteMeiSter:fix/chat-insurance-pause

Conversation

@ToteMeiSter

Copy link
Copy Markdown
Contributor

Symptom

With a high performance backend, a chat that stays in the back stack keeps sending GET .../chat/<token>?...lookIntoFuture=1&limit=200&timeout=0 every 2 minutes while the app is in the background, including all night with the screen off. In one server access log: 226 such requests from one device between 23:18 and 07:05, 120–122 s apart, all answered with 304.

Cause

  • OfflineFirstChatRepository.initInsuranceRequests() loops delay(INSURANCE_REQUEST_DELAY) → fetchNewMessages() and never checks the repository's pause flag.
  • initLongPolling() (used without the high performance backend) already waits while itIsPaused is set, so only the insurance loop runs in the background.
  • When the process is frozen and later woken (for example by a push), the overdue timer fires immediately.

Change

  • The insurance loop skips the request while itIsPaused is set, reusing the flag set by handleOnPause/handleOnResume. The loop keeps its normal 2-minute step.
  • No extra request on resume is needed: ChatViewModel.onResume already calls fetchNewMessages() right after handleOnResume() when the chat comes back to the foreground.
  • itIsPaused is now @Volatile: it is written on the main thread and read from the polling coroutine.

How to test

  1. Open a conversation on a server with a high performance backend, then press Home or lock the screen.
  2. Watch the server access log (or the app log) for 10 minutes.
  3. Before: a GET .../chat/<token>?...limit=200&timeout=0 every 2 minutes. After: none while the chat is paused.
  4. Return to the chat: one request right away, then every 2 minutes.

Unit tests: OfflineFirstChatRepositoryTest — insurance requests are skipped while the chat is paused, insurance requests resume with the next tick after the chat is resumed (both fail without the change; they use virtual time).

Not yet tested on a device after the change.

Related

Each of these background requests also cleared the user's chat notifications of that conversation, because fetchNewMessages() sends no markNotificationsAsRead=0; that is fixed separately in #6841. This PR touches the neighbouring initInsuranceRequests(); #6832 changes initLongPolling() just above it.

🖼️ Screenshots

Not applicable.

🚧 TODO

  • None

🏁 Checklist

  • ⛑️ Tests (unit and/or integration) are included or not needed
  • 🔖 Capability is checked or not needed
  • 🔙 Backport requests are created or not needed: /backport to stable-xx.x
  • 📅 Milestone is set
  • 🌸 PR title is meaningful (if it should be in the changelog: is it meaningful to users?)

🤖 AI (if applicable)

  • The content of this PR was partly or fully generated using AI

The analysis, code, tests and this description were prepared with Claude Code (claude-opus-5-5) and reviewed by me. The commit carries an Assisted-by trailer.

@coderabbitai

coderabbitai Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: c34a2ad1-d850-420e-b4cf-a65b0b873001

📥 Commits

Reviewing files that changed from the base of the PR and between 4f69e0b and 75e1e1c.


📒 Files selected for processing (1)
  • app/src/test/java/com/nextcloud/talk/chat/data/network/OfflineFirstChatRepositoryTest.kt

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 1 remain after this review.



📝 Walkthrough

Walkthrough

The repository marks itIsPaused as volatile and checks it after each insurance-polling delay. When the chat is paused, the loop skips the message fetch. Coroutine tests verify that polling stays inactive while paused and resumes on the next polling tick.


Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to 75e1e

Insurance polling skips paused chats and resumes on schedule. The tests verify actual network requests, and no actionable merge-blocking risk remains.

🚥 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%. Docstring coverage is scoped to functions touched by this diff. Analyzed 8 functions across 2 files. 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 clearly and concisely describes the main change: skipping insurance requests while the chat is paused.
Description check Passed The description follows the repository template and includes the symptom, cause, change, testing details, related work, TODO, checklist, screenshots, and AI disclosure. The backport and milestone item…
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.


  • Fix all pre-merge checks with AI
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
app/src/test/java/com/nextcloud/talk/chat/data/network/OfflineFirstChatRepositoryTest.kt (1)

235-238: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Verify that the resumed tick sends a request.

This test uses a fresh ChatMessageSyncer with no HTTP-synced anchor. fetchNewMessages() calls deleteExpiredMessages(), then returns without sending a network request. The assertion proves that the polling loop invoked the fetch method, but it does not prove the request behavior named in the test. Establish an HTTP-synced anchor in the fixture and verify the expected network.pullChatMessages() call.


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: e9e6ff96-3899-4ef6-ad93-907506599d95
📥 Commits

Reviewing files that changed from the base of the PR and between acc10f9 and 4f69e0b.

📒 Files selected for processing (2)
  • app/src/main/java/com/nextcloud/talk/chat/data/network/OfflineFirstChatRepository.kt
  • app/src/test/java/com/nextcloud/talk/chat/data/network/OfflineFirstChatRepositoryTest.kt

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 2 remain after this review.

@ToteMeiSter

ToteMeiSter commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor Author

@coderabbitai Thanks, the nitpick from your review on OfflineFirstChatRepositoryTest.kt (lines 235-238) is valid and is fixed in 75e1e1c9c.

The pause tests now record an HTTP-synced anchor through the initial load (loadInitialMessages), clear the mock invocations, and verify network.pullChatMessages() instead of deleteExpiredMessages():

  • while paused: no call over five insurance intervals;
  • after handleOnResume(): still no call half a tick later, exactly one call on the next tick.

Without the fix in this PR, both tests now fail with NeverWantedButInvoked on pullChatMessages. With the fix, the test class passes 33/33; ktlint is clean and the detekt count is unchanged from master.

AI disclosure: the test change was written with the help of Claude Code (claude-opus-5-5).

@coderabbitai

coderabbitai Bot commented Oct 9, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
fd -t f '^OfflineFirstChatRepositoryTest\.kt$' . | while IFS= read -r file; do
  ast-grep outline "$file" --match 'insurance|Initial|initial' --view expanded
  rg -n -C 30 'insurance requests are skipped|insurance requests resume|fun .*Initial|fun .*initial|loadInitialMessages\(' "$file"
done

Length of output: 11046


@ToteMeiSter Thanks for the fix. I checked OfflineFirstChatRepositoryTest.kt. The tests now establish the HTTP-synced anchor, clear the initial-load invocations, and verify network.pullChatMessages() directly.

The assertions cover five intervals without a request while paused, no request half a tick after resume, and exactly one request on the next tick. This addresses the test concern. I did not rerun the tests or lint checks.


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

You are interacting with an AI system.

@coderabbitai

coderabbitai Bot commented Oct 9, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
fd -t f '^OfflineFirstChatRepositoryTest\.kt$' . | while IFS= read -r file; do
  ast-grep outline "$file" --match 'insurance|Initial|initial' --view expanded
  rg -n -C 30 'insurance requests are skipped|insurance requests resume|fun .*Initial|fun .*initial|loadInitialMessages\(' "$file"
done

Length of output: 11046


@ToteMeiSter Thanks for the fix. I checked OfflineFirstChatRepositoryTest.kt. Both tests now establish the HTTP-synced anchor, clear the initial-load invocations, and verify network.pullChatMessages() directly.

The assertions cover five intervals without a request while paused, no request half a tick after resume, and exactly one request on the next tick. This addresses the test concern.

I did not rerun the tests or lint checks.

You are interacting with an AI system.

With a high performance backend the insurance loop sent a chat GET every
2 minutes for as long as ChatActivity stayed in the back stack, in the
background and overnight. Long polling already honours itIsPaused; the
insurance loop did not. Skip the tick while paused. Returning to the chat
is covered by ChatViewModel.onResume, which fetches immediately.

Signed-off-by: Krainov Gleb <krajnov.g@kontentplus.ru>
Assisted-by: Claude-Code:claude-opus-5-5
The pause tests counted deleteExpiredMessages calls, which only show that
fetchNewMessages ran: without an HTTP-synced anchor it returns before any
network request. Record an anchor through the initial load and verify
pullChatMessages instead: no call while paused, one call on the first
tick after the chat is resumed.

Signed-off-by: Krainov Gleb <krajnov.g@kontentplus.ru>
Assisted-by: Claude-Code:claude-opus-5-5
@mahibi
mahibi force-pushed the fix/chat-insurance-pause branch from 75e1e1c to bf3af05 Compare October 15, 2026 18:03
@mahibi
mahibi merged commit fbf4e82 into nextcloud:master Oct 15, 2026
10 of 19 checks passed
@AndyScherzinger AndyScherzinger added this to the 25.1.0 milestone Oct 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3. to review Waiting for reviews AI assisted

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants