Skip to content

Release mutex per attachment, persist incrementally, allow stopSync to interrupt mid-batch#974

Open
khawarizmus wants to merge 1 commit into
mainfrom
attachments-interrupts
Open

Release mutex per attachment, persist incrementally, allow stopSync to interrupt mid-batch#974
khawarizmus wants to merge 1 commit into
mainfrom
attachments-interrupts

Conversation

@khawarizmus
Copy link
Copy Markdown
Contributor

Summary

Ports powersync-ja/powersync.dart#415 to the JS SDK. Closes #971.

The issue

The AttachmentQueue mutex was held across the entire sync batch — including every per-attachment network upload/download. Foreground saveFile / deleteFile / watched-attachment processing all contend for the same mutex, so a slow or stalled upload hung foreground operations for the full duration. stopSync() also couldn't interrupt mid-batch.

The fix

  • SyncingService.processAttachments now runs each attachment's I/O outside the mutex and persists state per-row via a brief withContext re-acquire.
  • stopSync() aborts a new AbortController; the sync loop polls isActive() between attachments and exits within one attachment's processing time.
  • Watchers now observe per-attachment progress instead of one atomic commit at end of batch.

syncLoopMutex

The Dart version gets serialization of sync triggers for free from asyncMap. JS doesn't have that — setInterval, watchActiveAttachments.onDiff, and statusChanged all call syncStorage() independently, and the old wide mutex was implicitly serializing them. Added a dedicated syncLoopMutex to preserve that single-batch-at-a-time semantics without re-introducing the blocking. Foreground callers don't touch this lock, so #971 still goes away.

AI Disclosure

This PR was created with the help of Opus 4.7 and Claude Code. I’ve reviewed the resulting code changes and made sure tests are passing locally.

…ow mid-batch interruption

- Implemented incremental persistence of attachment states during sync.
- Updated `stopSync` to abort in-flight syncs promptly.
- Adjusted `processAttachments` to commit state changes immediately after each attachment's I/O operation, improving responsiveness for concurrent operations.
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 21, 2026

🦋 Changeset detected

Latest commit: b839d66

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 7 packages
Name Type
@powersync/common Patch
@powersync/node Patch
@powersync/op-sqlite Patch
@powersync/react-native Patch
@powersync/tanstack-react-query Patch
@powersync/web Patch
@powersync/diagnostics-app Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

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.

AttachmentQueue: foreground saveFile blocks for the full duration of an in-flight upload (shared mutex held across network I/O)

1 participant