@@ -76,10 +76,6 @@ export type WrappedSyncPort = {
7676 db ?: DBAdapter ;
7777 currentSubscriptions : SubscribedStream [ ] ;
7878 closeListeners : ( ( ) => void | Promise < void > ) [ ] ;
79- /**
80- * If we can use Navigator locks to detect if the client has closed.
81- */
82- isProtectedFromClose : boolean ;
8379 isClosing : boolean ;
8480} ;
8581
@@ -176,14 +172,16 @@ export class SharedSyncImplementation extends BaseObserver<SharedSyncImplementat
176172 /**
177173 * Gets the last client port which we know is safe from unexpected closes.
178174 */
179- protected get lastWrappedPort ( ) : WrappedSyncPort | undefined {
180- // Find the last port which is protected from close
181- for ( let i = this . ports . length - 1 ; i >= 0 ; i -- ) {
182- if ( this . ports [ i ] . isProtectedFromClose && ! this . ports [ i ] . isClosing ) {
183- return this . ports [ i ] ;
175+ protected async getLastWrappedPort ( ) : Promise < WrappedSyncPort | undefined > {
176+ // Find the last port which is not closing
177+ return await this . portMutex . runExclusive ( ( ) => {
178+ for ( let i = this . ports . length - 1 ; i >= 0 ; i -- ) {
179+ if ( ! this . ports [ i ] . isClosing ) {
180+ return this . ports [ i ] ;
181+ }
184182 }
185- }
186- return ;
183+ return ;
184+ } ) ;
187185 }
188186
189187 async waitForStatus ( status : SyncStatusOptions ) : Promise < void > {
@@ -232,44 +230,45 @@ export class SharedSyncImplementation extends BaseObserver<SharedSyncImplementat
232230 async setParams ( params : SharedSyncInitOptions ) {
233231 await this . portMutex . runExclusive ( async ( ) => {
234232 this . collectActiveSubscriptions ( ) ;
235- if ( this . syncParams ) {
236- // Cannot modify already existing sync implementation params
237- return ;
238- }
239-
240- // First time setting params
241- this . syncParams = params ;
242- if ( params . streamOptions ?. flags ?. broadcastLogs ) {
243- this . logger = this . broadCastLogger ;
244- }
233+ } ) ;
245234
246- const lockedAdapter = new LockedAsyncDatabaseAdapter ( {
247- name : params . dbParams . dbFilename ,
248- openConnection : async ( ) => {
249- // Gets a connection from the clients when a new connection is requested.
250- return await this . openInternalDB ( ) ;
251- } ,
252- logger : this . logger ,
253- reOpenOnConnectionClosed : true
254- } ) ;
255- this . distributedDB = lockedAdapter ;
256- await lockedAdapter . init ( ) ;
257-
258- lockedAdapter . registerListener ( {
259- databaseReOpened : ( ) => {
260- // We may have missed some table updates while the database was closed.
261- // We can poke the crud in case we missed any updates.
262- this . connectionManager . syncStreamImplementation ?. triggerCrudUpload ( ) ;
263- }
264- } ) ;
235+ if ( this . syncParams ) {
236+ // Cannot modify already existing sync implementation params
237+ return ;
238+ }
265239
266- self . onerror = ( event ) => {
267- // Share any uncaught events on the broadcast logger
268- this . logger . error ( 'Uncaught exception in PowerSync shared sync worker' , event ) ;
269- } ;
240+ // First time setting params
241+ this . syncParams = params ;
242+ if ( params . streamOptions ?. flags ?. broadcastLogs ) {
243+ this . logger = this . broadCastLogger ;
244+ }
270245
271- this . iterateListeners ( ( l ) => l . initialized ?.( ) ) ;
246+ const lockedAdapter = new LockedAsyncDatabaseAdapter ( {
247+ name : params . dbParams . dbFilename ,
248+ openConnection : async ( ) => {
249+ // Gets a connection from the clients when a new connection is requested.
250+ return await this . openInternalDB ( ) ;
251+ } ,
252+ logger : this . logger ,
253+ reOpenOnConnectionClosed : true
254+ } ) ;
255+ this . distributedDB = lockedAdapter ;
256+ await lockedAdapter . init ( ) ;
257+
258+ lockedAdapter . registerListener ( {
259+ databaseReOpened : ( ) => {
260+ // We may have missed some table updates while the database was closed.
261+ // We can poke the crud in case we missed any updates.
262+ this . connectionManager . syncStreamImplementation ?. triggerCrudUpload ( ) ;
263+ }
272264 } ) ;
265+
266+ self . onerror = ( event ) => {
267+ // Share any uncaught events on the broadcast logger
268+ this . logger . error ( 'Uncaught exception in PowerSync shared sync worker' , event ) ;
269+ } ;
270+
271+ this . iterateListeners ( ( l ) => l . initialized ?.( ) ) ;
273272 }
274273
275274 async dispose ( ) {
@@ -303,7 +302,6 @@ export class SharedSyncImplementation extends BaseObserver<SharedSyncImplementat
303302 clientProvider : Comlink . wrap < AbstractSharedSyncClientProvider > ( port ) ,
304303 currentSubscriptions : [ ] ,
305304 closeListeners : [ ] ,
306- isProtectedFromClose : false ,
307305 isClosing : false
308306 } satisfies WrappedSyncPort ;
309307 this . ports . push ( portProvider ) ;
@@ -409,7 +407,7 @@ export class SharedSyncImplementation extends BaseObserver<SharedSyncImplementat
409407 remote : new WebRemote (
410408 {
411409 invalidateCredentials : async ( ) => {
412- const lastPort = this . lastWrappedPort ;
410+ const lastPort = await this . getLastWrappedPort ( ) ;
413411 if ( ! lastPort ) {
414412 throw new Error ( 'No client port found to invalidate credentials' ) ;
415413 }
@@ -421,7 +419,7 @@ export class SharedSyncImplementation extends BaseObserver<SharedSyncImplementat
421419 }
422420 } ,
423421 fetchCredentials : async ( ) => {
424- const lastPort = this . lastWrappedPort ;
422+ const lastPort = await this . getLastWrappedPort ( ) ;
425423 if ( ! lastPort ) {
426424 throw new Error ( 'No client port found to fetch credentials' ) ;
427425 }
@@ -447,7 +445,7 @@ export class SharedSyncImplementation extends BaseObserver<SharedSyncImplementat
447445 this . logger
448446 ) ,
449447 uploadCrud : async ( ) => {
450- const lastPort = this . lastWrappedPort ;
448+ const lastPort = await this . getLastWrappedPort ( ) ;
451449 if ( ! lastPort ) {
452450 throw new Error ( 'No client port found to upload crud' ) ;
453451 }
@@ -483,7 +481,7 @@ export class SharedSyncImplementation extends BaseObserver<SharedSyncImplementat
483481 protected async openInternalDB ( ) {
484482 while ( true ) {
485483 try {
486- const lastClient = this . lastWrappedPort ;
484+ const lastClient = await this . getLastWrappedPort ( ) ;
487485 if ( ! lastClient ) {
488486 // Should not really happen in practice
489487 throw new Error ( `Could not open DB connection since no client is connected.` ) ;
@@ -563,19 +561,6 @@ export class SharedSyncImplementation extends BaseObserver<SharedSyncImplementat
563561 this . syncStatus = new SyncStatus ( status ) ;
564562 this . ports . forEach ( ( p ) => p . clientProvider . statusChanged ( status ) ) ;
565563 }
566-
567- /**
568- * A function only used for unit tests which updates the internal
569- * sync stream client and all tab client's sync status
570- */
571- async _testUpdateAllStatuses ( status : SyncStatusOptions ) {
572- if ( ! this . connectionManager . syncStreamImplementation ) {
573- throw new Error ( 'Cannot update status without a sync stream implementation' ) ;
574- }
575- // Only assigning, don't call listeners for this test
576- this . connectionManager . syncStreamImplementation ! . syncStatus = new SyncStatus ( status ) ;
577- this . updateAllStatuses ( status ) ;
578- }
579564}
580565
581566/**
0 commit comments