-
Notifications
You must be signed in to change notification settings - Fork 55
feat: Configurable Web VFS (added OPFS) #418
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
🦋 Changeset detectedLatest commit: f8cad95 The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
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 |
Unsolicited drive-by comment:
OPFS itself doesn't require the COOP/COEP headers and associated restrictions. Some SQLite VFS implementations use SharedArrayBuffer to provide a synchronous interface for SQLite, and that is what requires COOP/COEP, not OPFS. However, no example VFS in wa-sqlite uses SharedArrayBuffer. If you are using any VFS from the wa-sqlite project then COOP/COEP headers are unnecessary. |
Thank you for the tip/catch, @rhashimoto! I copied this from our Dart docs without fully verifying it yet, so this is really helpful. I'll review the relevant sections and update them as needed. It's a personal honor to have you comment on this. |
# Conflicts: # demos/react-supabase-todolist/package.json # packages/web/package.json # pnpm-lock.yaml
I don't have much context but reviewing the code everything seems in order |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall I like the new architecture, and I think OPFSCoopSyncVFS
is a good VFS to recommend.
The implementation also looks good overall, but I picked up some issues during testing.
I used the react-supabase-todolist
demo for testing, with the following setup:
const factory = new WASQLiteOpenFactory({
dbFilename: 'test.db',
vfs: WASQLiteVFS.OPFSCoopSyncVFS
});
export const db = new PowerSyncDatabase({
schema: AppSchema,
flags: {},
database: factory
});
There appears to be an issue with infinite update notification loops as soon as two databases are open, in the same tab or different tabs.
Test case 1: Single tab, hot reload
A hot reload opens a new copy of the database with its own dedicated worker, without closing the previous one. Not sure if this is an issue by itself, but it leads to constant 200% cpu usage, increasing further if you trigger more hot reloads.
Test case 2: Multiple tabs
As soon as you have multiple tabs open, you get the same CPU usage issue as above, even without hot reloading.
Another issue with multiple tabs is that the uploading status changes to true every second, then immediately back to false, after triggering a single change.
Profiling
When profiling with 2 tabs open, it seems like this block is repeatedly hit in the workers:
powersync-js/packages/web/src/db/adapters/wa-sqlite/WASQLiteConnection.ts
Lines 224 to 229 in 428686a
protected queueTableUpdate(tableNames: Set<string>) { | |
tableNames.forEach((tableName) => this.updatedTables.add(tableName)); | |
if (this.updateTimer == null) { | |
this.updateTimer = setTimeout(() => this.fireUpdates(), 0); | |
} | |
} |
This is what leads me to believe the issue is related to update notification loops.
IDBBatchAtomicVFS
I did not see any of the above issues when using IDBBatchAtomicVFS, although I haven't tested it as thoroughly.
@rkistner there were two fixes (two separate commits), where the issues were:
The outstanding issue is that the PS client isn't closed on HMR. An option we can try is to add a Vite specific handler to our Vite demos:
We might consider adding that in a follow-up PR. |
Overview
This POC adds support for configuring different SQLite virtual filesystems on Web.
WA-SQLite's
IDBBatchAtomicVFS
is still used as the default VFS.Synchronous Origin Private FileSystem (OPFS) VFS options are added. See WA-SQLite README for more details.
Notes
Configuration
OPFS can be configured with a
WASQLiteOpenFactory
. These options could be added to the default web constructor.Multiple Tab Support
The OPFS VFS currently only works in dedicated web workers. The current multiple tab support implementation has been updated in order to cater for this. For IndexDB we still use a single
SharedWorker
which manages a single SQLite connection between tabs. For OPFS each tab uses its own dedicatedWorker
which has its own SQLite connection. Table update notifications are shared between tabs via aBroadcastChannel
. Exclusive locks between tab connections are maintained through Navigator locks as usual.The initialisation for Web
DBAdapter
s has been streamlined and extended in order to support OPFS. The abstractions and sharing of implementation is managed by new internal APIs and classes.Safari Multiple Tab Support
The new code structure seemed to fix the long outstanding Safari multiple tab support issues when using
pnpm serve
but doing a build and usingpnpm preview
still shows the same problem.However, using OPFSCoopSyncVFS now provides multiple tab support for both Safari and Safari iOS.
This is not yet enabled by default but can be enabled with an appropriate flag.
OPFS VFS and Multiple tabs
The
AccessHandlePoolVFS
does not seem to work well when more than 1 dedicated worker accesses the filesystem.OPFSCoopSyncVFS
works with multiple tabs.Performance
OPFS (with AccessHandlePoolVFS) has been observed to be significantly faster than the IndexDB filesystem. The time to sync 23_000 rows was compared between IndexDB and OPFS
IndexDB

OPFS

Safari/Angular Demo
An issue was found with the Angular demo where it would not work with Safari, using OPFS resolves this - as such the demo has been updated.
Web Encryption
The #439 PR was merged into this branch and is meant to go into
main
with this changeset.TODOS