diff --git a/demos/react-supabase-todolist/src/components/providers/SystemProvider.tsx b/demos/react-supabase-todolist/src/components/providers/SystemProvider.tsx index a8648bfc..6e1e5e0f 100644 --- a/demos/react-supabase-todolist/src/components/providers/SystemProvider.tsx +++ b/demos/react-supabase-todolist/src/components/providers/SystemProvider.tsx @@ -17,7 +17,7 @@ export const db = new PowerSyncDatabase({ // dbFilename: 's.sqlite' // } database: new WASQLiteOpenFactory({ - dbFilename: 'examplsw1se11.db', + dbFilename: 'examplsw1se112.db', // vfs: WASQLiteVFS.OPFSCoopSyncVFS vfs: WASQLiteVFS.OPFSCoopSyncVFS //Out of memory errors on iOS Safari }) diff --git a/packages/web/src/db/PowerSyncDatabase.ts b/packages/web/src/db/PowerSyncDatabase.ts index ebb2ae3a..1d95fa6b 100644 --- a/packages/web/src/db/PowerSyncDatabase.ts +++ b/packages/web/src/db/PowerSyncDatabase.ts @@ -22,7 +22,7 @@ import { resolveWebSQLFlags, WebSQLFlags } from './adapters/web-sql-flags'; -import { WorkerDBAdapter } from './adapters/WorkerDBAdapter'; +import { WebDBAdapter } from './adapters/WebDBAdapter'; import { SharedWebStreamingSyncImplementation } from './sync/SharedWebStreamingSyncImplementation'; import { SSRStreamingSyncImplementation } from './sync/SSRWebStreamingSyncImplementation'; import { WebRemote } from './sync/WebRemote'; @@ -194,7 +194,7 @@ export class PowerSyncDatabase extends AbstractPowerSyncDatabase { } return new SharedWebStreamingSyncImplementation({ ...syncOptions, - workerDatabase: this.database as WorkerDBAdapter // This should always be the case + db: this.database as WebDBAdapter // This should always be the case }); default: return new WebStreamingSyncImplementation(syncOptions); diff --git a/packages/web/src/db/adapters/LockedAsyncDatabaseAdapter.ts b/packages/web/src/db/adapters/LockedAsyncDatabaseAdapter.ts index 89880329..2a2f0f54 100644 --- a/packages/web/src/db/adapters/LockedAsyncDatabaseAdapter.ts +++ b/packages/web/src/db/adapters/LockedAsyncDatabaseAdapter.ts @@ -11,6 +11,8 @@ import { import Logger, { ILogger } from 'js-logger'; import { getNavigatorLocks } from '../..//shared/navigator'; import { AsyncDatabaseConnection } from './AsyncDatabaseConnection'; +import { SharedConnectionWorker, WebDBAdapter } from './WebDBAdapter'; +import { WorkerWrappedAsyncDatabaseConnection } from './WorkerWrappedAsyncDatabaseConnection'; /** * @internal @@ -31,12 +33,14 @@ export type LockedAsyncDatabaseAdapterListener = DBAdapterListener & { * Wraps a {@link AsyncDatabaseConnection} and provides exclusive locking functions in * order to implement {@link DBAdapter}. */ -export class LockedAsyncDatabaseAdapter extends BaseObserver implements DBAdapter { +export class LockedAsyncDatabaseAdapter + extends BaseObserver + implements WebDBAdapter +{ private logger: ILogger; private dbGetHelpers: DBGetUtils | null; private debugMode: boolean; private _dbIdentifier: string; - private _isInitialized = false; protected initPromise: Promise; private _db: AsyncDatabaseConnection | null = null; protected _disposeTableChangeListener: (() => void) | null = null; @@ -79,6 +83,13 @@ export class LockedAsyncDatabaseAdapter extends BaseObserver { + if (false == this._db instanceof WorkerWrappedAsyncDatabaseConnection) { + throw new Error(`Only worker connections can be shared`); + } + return this._db.shareConnection(); + } + /** * Registers a table change notification callback with the base database. * This can be extended by custom implementations in order to handle proxy events. @@ -100,8 +111,6 @@ export class LockedAsyncDatabaseAdapter extends BaseObserver cb.initialized?.()); } diff --git a/packages/web/src/db/adapters/WebDBAdapter.ts b/packages/web/src/db/adapters/WebDBAdapter.ts new file mode 100644 index 00000000..b39c3712 --- /dev/null +++ b/packages/web/src/db/adapters/WebDBAdapter.ts @@ -0,0 +1,13 @@ +import { DBAdapter } from '@powersync/common'; + +export type SharedConnectionWorker = { + identifier: string; + port: MessagePort; +}; + +export interface WebDBAdapter extends DBAdapter { + /** + * Get a MessagePort which can be used to share the internals of this connection. + */ + shareConnection(): Promise; +} diff --git a/packages/web/src/db/adapters/WorkerDBAdapter.ts b/packages/web/src/db/adapters/WorkerDBAdapter.ts deleted file mode 100644 index 8ed6467e..00000000 --- a/packages/web/src/db/adapters/WorkerDBAdapter.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { DBAdapter } from '@powersync/common'; - -export interface WorkerDBAdapter extends DBAdapter { - /** - * Get a MessagePort which can be used to share the internals of this connection. - */ - getMessagePort(): Promise; -} diff --git a/packages/web/src/db/adapters/WorkerLockedAsyncDatabaseAdapter.ts b/packages/web/src/db/adapters/WorkerLockedAsyncDatabaseAdapter.ts deleted file mode 100644 index d2bfcaaf..00000000 --- a/packages/web/src/db/adapters/WorkerLockedAsyncDatabaseAdapter.ts +++ /dev/null @@ -1,47 +0,0 @@ -import * as Comlink from 'comlink'; -import { AsyncDatabaseConnection } from './AsyncDatabaseConnection'; -import { LockedAsyncDatabaseAdapter, LockedAsyncDatabaseAdapterOptions } from './LockedAsyncDatabaseAdapter'; -import { WorkerDBAdapter } from './WorkerDBAdapter'; -/** - * @internal - */ -export interface WorkerLockedAsyncDatabaseAdapterOptions extends LockedAsyncDatabaseAdapterOptions { - messagePort: Worker | MessagePort; -} - -export class WorkerLockedAsyncDatabaseAdapter extends LockedAsyncDatabaseAdapter implements WorkerDBAdapter { - /** - * Keep a reference to the worker port so that it can be shared - */ - private _messagePort: Worker | MessagePort; - - constructor(options: WorkerLockedAsyncDatabaseAdapterOptions) { - super(options); - this._messagePort = options.messagePort; - } - - /** - * Registers a table change notification callback with the base database. - * This can be extended by custom implementations in order to handle proxy events. - */ - protected async registerOnChangeListener(db: AsyncDatabaseConnection) { - this._disposeTableChangeListener = await db.registerOnTableChange( - Comlink.proxy((event) => { - this.iterateListeners((cb) => cb.tablesUpdated?.(event)); - }) - ); - } - - async getMessagePort(): Promise { - if (this._messagePort instanceof Worker) { - // We can't transfer a Worker instance, need a MessagePort - // Comlink provides a nice utility for exposing a MessagePort - // from a Worker - const temp = Comlink.wrap(this._messagePort); - const newPort = await temp[Comlink.createEndpoint](); - return newPort; - } - - return this._messagePort; - } -} diff --git a/packages/web/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.ts b/packages/web/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.ts new file mode 100644 index 00000000..831671e4 --- /dev/null +++ b/packages/web/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.ts @@ -0,0 +1,69 @@ +import * as Comlink from 'comlink'; +import { AsyncDatabaseConnection, OnTableChangeCallback, ProxiedQueryResult } from './AsyncDatabaseConnection'; + +export type SharedConnectionWorker = { + identifier: string; + port: MessagePort; +}; + +export type WrappedWorkerConnectionOptions = { + baseConnection: AsyncDatabaseConnection; + identifier: string; + worker: Worker | MessagePort; +}; + +/** + * Wraps a provided instance of {@link AsyncDatabaseConnection}, providing necessary proxy + * functions for worker listeners. + */ +export class WorkerWrappedAsyncDatabaseConnection implements AsyncDatabaseConnection { + constructor(protected options: WrappedWorkerConnectionOptions) {} + + protected get baseConnection() { + return this.options.baseConnection; + } + + init(): Promise { + return this.baseConnection.init(); + } + + /** + * Get a MessagePort which can be used to share the internals of this connection. + */ + async shareConnection(): Promise { + const { identifier, worker } = this.options; + if (worker instanceof Worker) { + // We can't transfer a Worker instance, need a MessagePort + // Comlink provides a nice utility for exposing a MessagePort + // from a Worker + const temp = Comlink.wrap(worker); + const newPort = await temp[Comlink.createEndpoint](); + return { port: newPort, identifier }; + } + + return { + identifier: identifier, + port: worker + }; + } + + /** + * Registers a table change notification callback with the base database. + * This can be extended by custom implementations in order to handle proxy events. + */ + async registerOnTableChange(callback: OnTableChangeCallback) { + return this.baseConnection.registerOnTableChange(Comlink.proxy(callback)); + } + + close(): Promise { + return this.baseConnection.close(); + } + + execute(sql: string, params?: any[]): Promise { + return this.baseConnection.execute(sql, params); + } + + executeBatch(sql: string, params?: any[]): Promise { + return this.baseConnection.executeBatch(sql, params); + } +} diff --git a/packages/web/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.ts b/packages/web/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.ts index a749e692..818f2ff6 100644 --- a/packages/web/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.ts +++ b/packages/web/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.ts @@ -1,6 +1,10 @@ import { type PowerSyncOpenFactoryOptions } from '@powersync/common'; +import * as Comlink from 'comlink'; +import { OpenAsyncDatabaseConnection } from '../AsyncDatabaseConnection'; +import { LockedAsyncDatabaseAdapter } from '../LockedAsyncDatabaseAdapter'; import { ResolvedWebSQLOpenOptions, WebSQLFlags } from '../web-sql-flags'; import { WASQLiteVFS } from './WASQLiteConnection'; +import { WASQLiteOpenFactory } from './WASQLiteOpenFactory'; /** * These flags are the same as {@link WebSQLFlags}. @@ -25,96 +29,29 @@ export interface WASQLiteDBAdapterOptions extends Omit implements DBAdapter { -// private initialized: Promise; -// private logger: ILogger; -// private dbGetHelpers: DBGetUtils | null; -// private methods: DBFunctionsInterface | null; -// private debugMode: boolean; - -// constructor(protected options: WASQLiteDBAdapterOptions) { -// super(); -// this.logger = Logger.get('WASQLite'); -// this.dbGetHelpers = null; -// this.methods = null; -// this.debugMode = options.debugMode ?? false; -// if (this.debugMode) { -// const originalExecute = this._execute.bind(this); -// this._execute = async (sql, bindings) => { -// const start = performance.now(); -// try { -// const r = await originalExecute(sql, bindings); -// performance.measure(`[SQL] ${sql}`, { start }); -// return r; -// } catch (e: any) { -// performance.measure(`[SQL] [ERROR: ${e.message}] ${sql}`, { start }); -// throw e; -// } -// }; -// } -// this.initialized = this.init(); -// this.dbGetHelpers = this.generateDBHelpers({ -// execute: (query, params) => this.acquireLock(() => this._execute(query, params)) -// }); -// } - -// get name() { -// return this.options.dbFilename; -// } - -// protected get flags(): Required { -// return resolveWebSQLFlags(this.options.flags ?? {}); -// } - -// getWorker() {} - -// protected async init() { -// const { enableMultiTabs, useWebWorker } = this.flags; -// if (!enableMultiTabs) { -// this.logger.warn('Multiple tabs are not enabled in this browser'); -// } - -// if (useWebWorker) { -// const optionsDbWorker = this.options.worker; - -// const dbOpener = this.options.workerPort -// ? Comlink.wrap(this.options.workerPort) -// : typeof optionsDbWorker === 'function' -// ? Comlink.wrap( -// resolveWorkerDatabasePortFactory(() => -// optionsDbWorker({ -// ...this.options, -// flags: this.flags -// }) -// ) -// ) -// : getWorkerDatabaseOpener(this.options.dbFilename, enableMultiTabs, optionsDbWorker); - -// this.methods = await dbOpener({ -// dbFileName: this.options.dbFilename, -// vfs: this.options.vfs -// }); -// this.methods.registerOnTableChange( -// Comlink.proxy((event) => { -// this.iterateListeners((cb) => cb.tablesUpdated?.(event)); -// }) -// ); - -// return; -// } - -// // Not using a worker -// const connection = new WASqliteConnection({ -// dbFileName: this.options.dbFilename -// }); -// await connection.init(); - -// this.methods = connection; -// this.methods.registerOnTableChange((event) => { -// this.iterateListeners((cb) => cb.tablesUpdated?.(event)); -// }); -// } - -// async refreshSchema(): Promise {} -// } +export class WASQLiteDBAdapter extends LockedAsyncDatabaseAdapter { + constructor(options: WASQLiteDBAdapterOptions) { + super({ + name: options.dbFilename, + openConnection: async () => { + const { workerPort } = options; + if (workerPort) { + const wrapped = Comlink.wrap(workerPort); + return wrapped(options); + } + const openFactory = new WASQLiteOpenFactory({ + dbFilename: options.dbFilename, + dbLocation: options.dbLocation, + debugMode: options.debugMode, + flags: options.flags, + logger: options.logger, + vfs: options.vfs, + worker: options.worker + }); + return openFactory.openConnection(); + }, + debugMode: options.debugMode, + logger: options.logger + }); + } +} diff --git a/packages/web/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.ts b/packages/web/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.ts index 858ae47e..aceabd46 100644 --- a/packages/web/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.ts +++ b/packages/web/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.ts @@ -2,10 +2,10 @@ import { DBAdapter } from '@powersync/common'; import * as Comlink from 'comlink'; import { openWorkerDatabasePort, resolveWorkerDatabasePortFactory } from '../../../worker/db/open-worker-database'; import { AbstractWebSQLOpenFactory } from '../AbstractWebSQLOpenFactory'; -import { OpenAsyncDatabaseConnection } from '../AsyncDatabaseConnection'; +import { AsyncDatabaseConnection, OpenAsyncDatabaseConnection } from '../AsyncDatabaseConnection'; import { LockedAsyncDatabaseAdapter } from '../LockedAsyncDatabaseAdapter'; import { WebSQLOpenFactoryOptions } from '../web-sql-flags'; -import { WorkerLockedAsyncDatabaseAdapter } from '../WorkerLockedAsyncDatabaseAdapter'; +import { WorkerWrappedAsyncDatabaseConnection } from '../WorkerWrappedAsyncDatabaseConnection'; import { WASqliteConnection, WASQLiteOpenOptions, WASQLiteVFS } from './WASQLiteConnection'; export interface WASQLiteOpenFactoryOptions extends WebSQLOpenFactoryOptions { @@ -26,17 +26,24 @@ export class WASQLiteOpenFactory extends AbstractWebSQLOpenFactory { } protected openAdapter(): DBAdapter { + return new LockedAsyncDatabaseAdapter({ + name: this.options.dbFilename, + openConnection: () => this.openConnection(), + debugMode: this.options.debugMode, + logger: this.logger + }); + } + + async openConnection(): Promise { const { enableMultiTabs, useWebWorker } = this.resolvedFlags; if (!enableMultiTabs) { this.logger.warn('Multiple tabs are not enabled in this browser'); } - let adapter: DBAdapter; - if (useWebWorker) { const optionsDbWorker = this.options.worker; - const messagePort = + const workerPort = typeof optionsDbWorker == 'function' ? resolveWorkerDatabasePortFactory(() => optionsDbWorker({ @@ -46,37 +53,26 @@ export class WASQLiteOpenFactory extends AbstractWebSQLOpenFactory { ) : openWorkerDatabasePort(this.options.dbFilename, enableMultiTabs, optionsDbWorker, this.waOptions.vfs); - const workerDBOpener = Comlink.wrap>(messagePort); + const workerDBOpener = Comlink.wrap>(workerPort); - adapter = new WorkerLockedAsyncDatabaseAdapter({ - messagePort, - openConnection: () => - workerDBOpener({ - dbFilename: this.options.dbFilename, - vfs: this.waOptions.vfs, - flags: this.resolvedFlags - }), - name: this.options.dbFilename, - debugMode: this.options.debugMode, - logger: this.logger + return new WorkerWrappedAsyncDatabaseConnection({ + baseConnection: await workerDBOpener({ + dbFilename: this.options.dbFilename, + vfs: this.waOptions.vfs, + flags: this.resolvedFlags + }), + identifier: this.options.dbFilename, + worker: workerPort }); } else { // Don't use a web worker - adapter = new LockedAsyncDatabaseAdapter({ - openConnection: async () => - new WASqliteConnection({ - dbFilename: this.options.dbFilename, - dbLocation: this.options.dbLocation, - debugMode: this.options.debugMode, - vfs: this.waOptions.vfs, - flags: this.resolvedFlags - }), - name: this.options.dbFilename, + return new WASqliteConnection({ + dbFilename: this.options.dbFilename, + dbLocation: this.options.dbLocation, debugMode: this.options.debugMode, - logger: this.logger + vfs: this.waOptions.vfs, + flags: this.resolvedFlags }); } - - return adapter; } } diff --git a/packages/web/src/db/sync/SharedWebStreamingSyncImplementation.ts b/packages/web/src/db/sync/SharedWebStreamingSyncImplementation.ts index bda4b32c..783e8fc3 100644 --- a/packages/web/src/db/sync/SharedWebStreamingSyncImplementation.ts +++ b/packages/web/src/db/sync/SharedWebStreamingSyncImplementation.ts @@ -7,7 +7,7 @@ import { SharedSyncImplementation } from '../../worker/sync/SharedSyncImplementation'; import { resolveWebSQLFlags } from '../adapters/web-sql-flags'; -import { WorkerDBAdapter } from '../adapters/WorkerDBAdapter'; +import { WebDBAdapter } from '../adapters/WebDBAdapter'; import { WebStreamingSyncImplementation, WebStreamingSyncImplementationOptions @@ -21,14 +21,13 @@ class SharedSyncClientProvider extends AbstractSharedSyncClientProvider { constructor( protected options: WebStreamingSyncImplementationOptions, public statusChanged: (status: SyncStatusOptions) => void, - protected dbWorkerPort: Promise + protected webDB: WebDBAdapter ) { super(); } async getDBWorkerPort(): Promise { - // This is provided asynchronously for an easier initialization - const port = await this.dbWorkerPort; + const { port } = await this.webDB.shareConnection(); return Comlink.transfer(port, [port]); } @@ -89,7 +88,7 @@ class SharedSyncClientProvider extends AbstractSharedSyncClientProvider { } export interface SharedWebStreamingSyncImplementationOptions extends WebStreamingSyncImplementationOptions { - workerDatabase: WorkerDBAdapter; + db: WebDBAdapter; } export class SharedWebStreamingSyncImplementation extends WebStreamingSyncImplementation { @@ -163,7 +162,7 @@ export class SharedWebStreamingSyncImplementation extends WebStreamingSyncImplem (status) => { this.iterateListeners((l) => this.updateSyncStatus(status)); }, - options.workerDatabase.getMessagePort() + options.db ); /** diff --git a/packages/web/src/worker/sync/SharedSyncImplementation.ts b/packages/web/src/worker/sync/SharedSyncImplementation.ts index c2458114..ee80e309 100644 --- a/packages/web/src/worker/sync/SharedSyncImplementation.ts +++ b/packages/web/src/worker/sync/SharedSyncImplementation.ts @@ -21,8 +21,9 @@ import { } from '../../db/sync/WebStreamingSyncImplementation'; import { OpenAsyncDatabaseConnection } from '../../db/adapters/AsyncDatabaseConnection'; +import { LockedAsyncDatabaseAdapter } from '../../db/adapters/LockedAsyncDatabaseAdapter'; import { WASQLiteOpenOptions } from '../../db/adapters/wa-sqlite/WASQLiteConnection'; -import { WorkerLockedAsyncDatabaseAdapter } from '../../db/adapters/WorkerLockedAsyncDatabaseAdapter'; +import { WorkerWrappedAsyncDatabaseConnection } from '../../db/adapters/WorkerWrappedAsyncDatabaseConnection'; import { getNavigatorLocks } from '../../shared/navigator'; import { AbstractSharedSyncClientProvider } from './AbstractSharedSyncClientProvider'; import { BroadcastLogger } from './BroadcastLogger'; @@ -158,21 +159,24 @@ export class SharedSyncImplementation // TODO share logic here const lastClient = this.ports[this.ports.length - 1]; const workerPort = await lastClient.clientProvider.getDBWorkerPort(); - const locked = new WorkerLockedAsyncDatabaseAdapter({ - name: this.syncParams?.dbName!, - messagePort: workerPort, + const locked = new LockedAsyncDatabaseAdapter({ + name: this.syncParams!.dbName, openConnection: async () => { const remote = Comlink.wrap>(workerPort); - return remote({ - dbFilename: this.syncParams!.dbName, - // TODO improve - flags: { - enableMultiTabs: true, - useWebWorker: true, - broadcastLogs: true, - disableSSRWarning: true, - ssrMode: false - } + return new WorkerWrappedAsyncDatabaseConnection({ + baseConnection: await remote({ + dbFilename: this.syncParams!.dbName, + // TODO improve + flags: { + enableMultiTabs: true, + useWebWorker: true, + broadcastLogs: true, + disableSSRWarning: true, + ssrMode: false + } + }), + identifier: this.syncParams!.dbName, + worker: workerPort }); }, logger: this.logger @@ -269,29 +273,30 @@ export class SharedSyncImplementation }); if (this.dbAdapter == trackedPort.db && this.syncStreamClient) { - // The db adapter belonged to a client which has closed. We need to reconnect - // FIXME better closing - // this.dbAdapter!.close(); + this.dbAdapter!.close(); await this.disconnect(); // Ask for a new DB worker port handler const lastClient = this.ports[this.ports.length - 1]; const workerPort = await lastClient.clientProvider.getDBWorkerPort(); - const locked = new WorkerLockedAsyncDatabaseAdapter({ - name: this.syncParams?.dbName!, - messagePort: workerPort, + const locked = new LockedAsyncDatabaseAdapter({ + name: this.syncParams!.dbName, openConnection: async () => { const remote = Comlink.wrap>(workerPort); - return remote({ - dbFilename: this.syncParams!.dbName, - // TODO improve - flags: { - enableMultiTabs: true, - useWebWorker: true, - broadcastLogs: true, - disableSSRWarning: true, - ssrMode: false - } + return new WorkerWrappedAsyncDatabaseConnection({ + baseConnection: await remote({ + dbFilename: this.syncParams!.dbName, + // TODO improve + flags: { + enableMultiTabs: true, + useWebWorker: true, + broadcastLogs: true, + disableSSRWarning: true, + ssrMode: false + } + }), + identifier: this.syncParams!.dbName, + worker: workerPort }); }, logger: this.logger diff --git a/packages/web/tests/multiple_instances.test.ts b/packages/web/tests/multiple_instances.test.ts index 60580981..cdb0ea26 100644 --- a/packages/web/tests/multiple_instances.test.ts +++ b/packages/web/tests/multiple_instances.test.ts @@ -8,7 +8,7 @@ import { import { Mutex } from 'async-mutex'; import Logger from 'js-logger'; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'; -import { WorkerDBAdapter } from '../src/db/adapters/WorkerDBAdapter'; +import { WebDBAdapter } from '../src/db/adapters/WebDBAdapter'; import { TestConnector } from './utils/MockStreamOpenFactory'; import { testSchema } from './utils/testDb'; @@ -134,7 +134,7 @@ describe('Multiple Instances', () => { await connector1.uploadData(db); }, identifier, - workerDatabase: db.database as WorkerDBAdapter + db: db.database as WebDBAdapter }; const stream1 = new SharedWebStreamingSyncImplementation(syncOptions1); @@ -148,7 +148,7 @@ describe('Multiple Instances', () => { await connector2.uploadData(db); }, identifier, - workerDatabase: db.database as WorkerDBAdapter + db: db.database as WebDBAdapter }; const stream2 = new SharedWebStreamingSyncImplementation(syncOptions2); @@ -196,7 +196,7 @@ describe('Multiple Instances', () => { triggerUpload1(); connector1.uploadData(db); }, - workerDatabase: db.database as WorkerDBAdapter, + db: db.database as WebDBAdapter, identifier, retryDelayMs: 100, flags: { @@ -227,7 +227,7 @@ describe('Multiple Instances', () => { flags: { broadcastLogs: true }, - workerDatabase: db.database as WorkerDBAdapter + db: db.database as WebDBAdapter }); // Waits for the stream to be marked as connected