-
Notifications
You must be signed in to change notification settings - Fork 351
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
[Feature Request] Shared web indexedDB database without using Worker or SharedWorker #2917
Comments
The problem is that IndexedDB reads are asynchronous, whereas sqlite3, being a C library, expects a synchronous file system. With OPFS that's no problem, but with IndexedDB we need to cheat. Essentially, the implementation works by loading the entire database into memory before opening it, and then asynchronously updating IndexedDB when the in-memory copy changes. Is the background service a singleton? If so, you could essentially use that service as a shared worker, with the foreground app connecting to it to access the database. |
I see
Yes, it is a singleton. I tried to do this but adding the following code in the background service driftWorkerMain(() {
return WebDatabase.withStorage(
DriftWebStorage.indexedDb(
'my_app_db',
migrateFromLocalStorage: false,
inWebWorker: true,
),
);
}); throws |
Update: I managed to get it working with the following web implementation: import 'dart:html';
import 'package:drift/drift.dart';
import 'package:drift/web.dart';
import 'package:drift/web/worker.dart';
QueryExecutor connect({required bool isWebBackgroundService}) {
if (isWebBackgroundService) {
WorkerGlobalScope.instance.importScripts('sql-wasm.js');
final QueryExecutor queryExecutor = WebDatabase.withStorage(
DriftWebStorage.indexedDb(
'my_app_db',
migrateFromLocalStorage: false,
inWebWorker: true,
),
);
driftWorkerMain(() => queryExecutor);
return queryExecutor;
} else {
return DatabaseConnection.delayed(
connectToDriftWorker(
"background_service.web.js",
mode: DriftWorkerMode.shared,
),
);
}
} AND with the following change for drift to force accept my background service as a shared worker: void driftWorkerMain(QueryExecutor Function() openConnection) {
final self = WorkerGlobalScope.instance;
final _RunningDriftWorker worker = _RunningDriftWorker(true, openConnection);
// if (self is SharedWorkerGlobalScope) {
// worker = _RunningDriftWorker(true, openConnection);
// } else if (self is DedicatedWorkerGlobalScope) {
// worker = _RunningDriftWorker(false, openConnection);
// } else {
// throw StateError('This worker is neither a shared nor a dedicated worker');
// }
worker.start();
} |
Another Update: While the above solution runs with no visible errors, the 2 databases seem to be out of sync. When I update the database via the extension window/page, the When I fully restart the background service (and it loads again the DB from indexedDB), it picks up the change. |
Is the background worker opening an independent database connection or are you connecting it to the drift server already? If there are two separate There's no API for this at the moment, but since you're making modifications you can use DriftServer server = ...;
final channel = StreamChannelController();
server.serve(channel.foreign, serialize: false);
final connection =
await connectToRemoteAndInitialize(channel.local, serialize: false);
|
I was trying to not rely on the drift server at all for the DB connection of the background service. So, what I have is:
I think this approach should normally work (for the most part) to share the same database between the two. Update since my last comment: I think the issue is actually a bigger one, making this more like a completely new feature as opposed to something to be slightly retrofitted. The APIs used to communicate between the chrome background service and the extension window is actually not exactly the same as the one used by workers. To create a MessagePort, I need:
This needs quite a bit more dart-js interop done ofc. I already did a rough proof of concept for this. Now, The foreground and background are sharing the same database (after updating the DB in foreground, the background db also picks up the change) The issues: I think this can work, but also seems different enough to warrant a new |
I added this draft pull request with my changes to have a better idea of what I did. P.s. That is insanely rough proof of concept code to test if it would work. There's no "good coding practices" being followed. |
Did your debugging code to print the type reveal the problem? If you're using the new interop APIs you might have to call
Huh, it should. It might be that the foreground thinks its the only connection user if the mode is not
It's very cool work, but I think it's too niche to be included in |
Is your feature request related to a problem? Please describe.
I am working on a chrome extension app (using manifest V3). This app has a background service. I want to access the same database (shared) between the foreground app of the extension and the background service.
The problem
The current implementation of shared web database uses the
Worker
andSharedWorker
classes. Those do not exist in the context of chrome extension background service.Can this even work
The indexedDB is shared between the extension tab and the background service. So it should be possible for both to read/write on the same database.
The text was updated successfully, but these errors were encountered: