Skip to content

Don't delete conversations that arrive while a list sync is in flight - #6749

Draft
AndyScherzinger wants to merge 1 commit into
masterfrom
fix/noid/no-conversation-loss-on-concurrent-sync
Draft

AndyScherzinger wants to merge 1 commit into
masterfrom
fix/noid/no-conversation-loss-on-concurrent-sync

Conversation

@AndyScherzinger

Copy link
Copy Markdown
Member

A conversation list sync reads the locally known conversations after the server has answered, and treats every one the response does not mention as a conversation the user left. A conversation that reached the database while the request was in flight — a single-room fetch, a room joined on another device, one the user just created — was never in that response and could not have been, so it was deleted, taking its cached messages and chat blocks with it through the foreign key cascade.

What it does

Takes the set of known conversation ids before the request goes out, and reconciles removals only against those. A conversation that appeared afterwards is left alone until the next full sync, which is the first one whose response could actually speak about it.

Why not simply read the conversations earlier

The same read feeds preservePendingLocalState, which needs the freshest local state to protect an in-flight favourite or read marker. Moving it earlier would trade this bug for that one. Only the removal reconcile wants the older snapshot, so only it gets one — as an id-only query, so the extra read does not load every conversation row.

Note for reviewers

detekt is red on this branch. It is red on master too, at the same count: 111 weighted issues against a maxIssues of 110, measured on master with this branch stashed. This change adds none.

🚧 TODO

  • ...

🏁 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

A conversation list sync reads the locally known conversations after the
server has answered, and treats every one the response does not mention
as a conversation the user left. A conversation that reached the
database while the request was in flight - a single-room fetch, a room
joined on another device, one the user just created - was never in that
response and could not have been, so it was deleted, taking its cached
messages and chat blocks with it through the foreign key cascade.

Take the known conversation ids before the request goes out and
reconcile removals only against those. Anything that appeared afterwards
is left alone until the next full sync, which is the first one whose
response can speak about it at all.

Reading the conversations themselves earlier would not do: that same
read feeds the pending local state guard, which needs the freshest state
to protect a favourite or read marker that is still on its way to the
server. Only the removal reconcile wants the older snapshot, so only it
gets one, as an id query that does not load the rows.

Assisted-by: Claude Code:claude-opus-5
Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
@AndyScherzinger AndyScherzinger added this to the 25.1.0 milestone Sep 21, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📱 QA build

Download app-qa-debug.apk
QR code Open the QR code for this download
Commit ec58558
Version 6749
Available until 7 days after this build

The QA build installs alongside a released Nextcloud app, so you can keep
using your existing install while testing.

Downloading the file requires a GitHub account, so open this link on the
device you want to test on, or transfer the APK to it.

@AndyScherzinger AndyScherzinger added the 2. developing Work in progress label Sep 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant