@@ -21,9 +21,9 @@ import {
2121} from '../../db/sync/WebStreamingSyncImplementation' ;
2222
2323import { WASQLiteDBAdapter } from '../../db/adapters/wa-sqlite/WASQLiteDBAdapter' ;
24+ import { getNavigatorLocks } from '../../shared/navigator' ;
2425import { AbstractSharedSyncClientProvider } from './AbstractSharedSyncClientProvider' ;
2526import { BroadcastLogger } from './BroadcastLogger' ;
26- import { getNavigatorLocks } from '../../shared/navigator' ;
2727
2828/**
2929 * Manual message events for shared sync clients
@@ -46,13 +46,20 @@ export type SharedSyncInitOptions = {
4646 streamOptions : Omit < WebStreamingSyncImplementationOptions , 'adapter' | 'uploadCrud' | 'remote' > ;
4747} ;
4848
49+ type TrackedClientDB = {
50+ client : AbstractSharedSyncClientProvider ;
51+ db : DBAdapter ;
52+ port : MessagePort ;
53+ } ;
54+
4955export interface SharedSyncImplementationListener extends StreamingSyncImplementationListener {
5056 initialized : ( ) => void ;
5157}
5258
5359export type WrappedSyncPort = {
5460 port : MessagePort ;
5561 clientProvider : Comlink . Remote < AbstractSharedSyncClientProvider > ;
62+ db ?: DBAdapter ;
5663} ;
5764
5865export type RemoteOperationAbortController = {
@@ -79,6 +86,7 @@ export class SharedSyncImplementation
7986 protected dbAdapter : DBAdapter | null ;
8087 protected syncParams : SharedSyncInitOptions | null ;
8188 protected logger : ILogger ;
89+ protected lastConnectOptions : PowerSyncConnectionOptions | undefined ;
8290
8391 syncStatus : SyncStatus ;
8492 broadCastLogger : ILogger ;
@@ -90,6 +98,7 @@ export class SharedSyncImplementation
9098 this . syncParams = null ;
9199 this . syncStreamClient = null ;
92100 this . logger = Logger . get ( 'shared-sync' ) ;
101+ this . lastConnectOptions = undefined ;
93102
94103 this . isInitialized = new Promise ( ( resolve ) => {
95104 const callback = this . registerListener ( {
@@ -124,19 +133,12 @@ export class SharedSyncImplementation
124133 /**
125134 * Configures the DBAdapter connection and a streaming sync client.
126135 */
127- async init ( dbWorkerPort : MessagePort , params : SharedSyncInitOptions ) {
128- if ( this . dbAdapter ) {
136+ async setParams ( params : SharedSyncInitOptions ) {
137+ if ( this . syncParams ) {
129138 // Cannot modify already existing sync implementation
130139 return ;
131140 }
132141
133- this . dbAdapter = new WASQLiteDBAdapter ( {
134- dbFilename : params . dbName ,
135- workerPort : dbWorkerPort ,
136- flags : { enableMultiTabs : true , useWebWorker : true } ,
137- logger : this . logger
138- } ) ;
139-
140142 this . syncParams = params ;
141143
142144 if ( params . streamOptions ?. flags ?. broadcastLogs ) {
@@ -148,6 +150,19 @@ export class SharedSyncImplementation
148150 this . logger . error ( 'Uncaught exception in PowerSync shared sync worker' , event ) ;
149151 } ;
150152
153+ // Ask for a new DB worker port handler
154+ // We can only ask once per client provider since the port
155+ // can only be transferred once
156+ // TODO share logic here
157+ const lastClient = this . ports [ this . ports . length - 1 ] ;
158+ const workerPort = await lastClient . clientProvider . getDBWorkerPort ( ) ;
159+ this . dbAdapter = lastClient . db = new WASQLiteDBAdapter ( {
160+ dbFilename : this . syncParams ?. dbName ! ,
161+ workerPort,
162+ flags : { enableMultiTabs : true , useWebWorker : true } ,
163+ logger : this . logger
164+ } ) ;
165+
151166 this . iterateListeners ( ( l ) => l . initialized ?.( ) ) ;
152167 }
153168
@@ -168,7 +183,7 @@ export class SharedSyncImplementation
168183 // This effectively queues connect and disconnect calls. Ensuring multiple tabs' requests are synchronized
169184 return getNavigatorLocks ( ) . request ( 'shared-sync-connect' , async ( ) => {
170185 this . syncStreamClient = this . generateStreamingImplementation ( ) ;
171-
186+ this . lastConnectOptions = options ;
172187 this . syncStreamClient . registerListener ( {
173188 statusChanged : ( status ) => {
174189 this . updateAllStatuses ( status . toJSON ( ) ) ;
@@ -210,14 +225,18 @@ export class SharedSyncImplementation
210225 * Removes a message port client from this manager's managed
211226 * clients.
212227 */
213- removePort ( port : MessagePort ) {
228+ async removePort ( port : MessagePort ) {
214229 const index = this . ports . findIndex ( ( p ) => p . port == port ) ;
215230 if ( index < 0 ) {
216231 console . warn ( `Could not remove port ${ port } since it is not present in active ports.` ) ;
217232 return ;
218233 }
219234
220235 const trackedPort = this . ports [ index ] ;
236+ if ( trackedPort . db ) {
237+ trackedPort . db . close ( ) ;
238+ }
239+
221240 // Release proxy
222241 trackedPort . clientProvider [ Comlink . releaseProxy ] ( ) ;
223242 this . ports . splice ( index , 1 ) ;
@@ -231,6 +250,25 @@ export class SharedSyncImplementation
231250 abortController ! . controller . abort ( new AbortOperation ( 'Closing pending requests after client port is removed' ) ) ;
232251 }
233252 } ) ;
253+
254+ if ( this . dbAdapter == trackedPort . db && this . syncStreamClient ) {
255+ // The db adapter belonged to a client which has closed. We need to reconnect
256+ // FIXME better closing
257+ // this.dbAdapter!.close();
258+
259+ await this . disconnect ( ) ;
260+ // Ask for a new DB worker port handler
261+ const lastClient = this . ports [ this . ports . length - 1 ] ;
262+ const workerPort = await lastClient . clientProvider . getDBWorkerPort ( ) ;
263+
264+ this . dbAdapter = lastClient . db = new WASQLiteDBAdapter ( {
265+ dbFilename : this . syncParams ?. dbName ! ,
266+ workerPort,
267+ flags : { enableMultiTabs : true , useWebWorker : true } ,
268+ logger : this . logger
269+ } ) ;
270+ await this . connect ( this . lastConnectOptions ) ;
271+ }
234272 }
235273
236274 triggerCrudUpload ( ) {
0 commit comments