Skip to content

fix: don't lose persistence silently under relaxedDurability#1063

Open
AntonOfTheWoods wants to merge 1 commit into
electric-sql:mainfrom
pgxsinkit:fix/relaxed-sync-latch-and-close-drain
Open

fix: don't lose persistence silently under relaxedDurability#1063
AntonOfTheWoods wants to merge 1 commit into
electric-sql:mainfrom
pgxsinkit:fix/relaxed-sync-latch-and-close-drain

Conversation

@AntonOfTheWoods

Copy link
Copy Markdown
Contributor

Two related fixes for the fire-and-forget sync path:

  • A failed background sync was an unhandled promise rejection and the database kept running without ever persisting again. Latch the first failure and throw it from the next query or explicit syncToFs() call.
  • close() could close the filesystem while a detached sync was still running against it — on IdbFs the in-flight sync would open a transaction on an already-closing IDBDatabase connection (an uncaught InvalidStateError from inside an Emscripten callback, reproduced on Chrome and Firefox) and the tail writes could be dropped. Drain the in-flight sync and perform a final strict sync before closeFs(), always release filesystem resources, and report a final-sync failure to the caller.

@AntonOfTheWoods
AntonOfTheWoods force-pushed the fix/relaxed-sync-latch-and-close-drain branch from 2d58151 to f8329f5 Compare July 20, 2026 13:41
Two related fixes for the fire-and-forget sync path:

- A failed background sync was an unhandled promise rejection and the
  database kept running without ever persisting again. Latch the first
  failure and throw it from the next query or explicit syncToFs() call.
- close() could close the filesystem while a detached sync was still
  running against it — on IdbFs the in-flight sync would open a
  transaction on an already-closing IDBDatabase connection (an uncaught
  InvalidStateError from inside an Emscripten callback, reproduced on
  Chrome and Firefox) and the tail writes could be dropped. Drain the
  in-flight sync and perform a final strict sync before closeFs(),
  always release filesystem resources, and report a final-sync failure
  to the caller.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@AntonOfTheWoods
AntonOfTheWoods force-pushed the fix/relaxed-sync-latch-and-close-drain branch from f8329f5 to c944cb6 Compare July 21, 2026 03:38
@AntonOfTheWoods

Copy link
Copy Markdown
Contributor Author

Revised: the failure latch is now scoped to the detached (fire-and-forget) path only. The originally pushed version also latched awaited sync failures before rethrowing — but there the caller already receives the rejection, and replaying it on the next syncToFs() shadows a stateful custom filesystem's own failure policy (we hit this downstream: the replay masked our VFS's poisoned-store error type). Added a regression test covering the awaited path (does NOT latch an awaited failure).

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.

1 participant