Skip to content

fix: flush table-update notifications while holding the write mutex#1

Merged
austinbhale merged 1 commit into
mainfrom
fix/flush-updates-under-write-mutex
Jun 10, 2026
Merged

fix: flush table-update notifications while holding the write mutex#1
austinbhale merged 1 commit into
mainfrom
fix/flush-updates-under-write-mutex

Conversation

@austinbhale

Copy link
Copy Markdown
Member

Problem

MDSQLiteAdapter.WriteLock (both overloads) calls writeConnection.FlushUpdates() after releasing writeMutex. FlushUpdates() enumerates the connection's updateBuffer (a plain List<>), which the SQLite update hook appends to from whichever thread is executing a write. With two overlapping WriteLock calls, the second caller's hook fires while the first is still enumerating:

System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
   at PowerSync.Common.MDSQLite.MDSQLiteAdapter.WriteLockT (...)

The late flush also misattributes updates: a concurrent writer's entries can land in another caller's TablesUpdatedEvent batch or be lost to its Clear(), so Watch queries can silently miss changes.

Fix

Move FlushUpdates() inside the mutex. The update hook only fires during writes, which only happen under the mutex, so the buffer becomes single-threaded by construction. No deadlock risk: EventStream.Emit is a non-blocking Channel.Writer.TryWrite and subscribers consume on their own tasks.

Copilot AI 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.

Pull request overview

This PR fixes a concurrency bug in MDSQLiteAdapter.WriteLock where writeConnection.FlushUpdates() could enumerate MDSQLiteConnection’s updateBuffer concurrently with the SQLite update hook appending to it, causing InvalidOperationException and potentially mis-batching or losing table-update notifications.

Changes:

  • Move writeConnection.FlushUpdates() to execute while holding writeMutex in both WriteLock overloads.
  • Ensure update notifications are flushed/cleared deterministically within the single-writer critical section, preventing concurrent mutation during enumeration.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@austinbhale austinbhale merged commit 4193095 into main Jun 10, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants