@@ -113,23 +113,28 @@ export class LockedAsyncDatabaseAdapter
113113 }
114114
115115 protected async openInternalDB ( ) {
116- // Dispose any previous table change listener.
117- this . _disposeTableChangeListener ?.( ) ;
118- this . _disposeTableChangeListener = null ;
119-
120- const isReOpen = ! ! this . _db ;
121-
122- this . _db = await this . options . openConnection ( ) ;
123- await this . _db . init ( ) ;
124- this . _config = await this . _db . getConfig ( ) ;
125- await this . registerOnChangeListener ( this . _db ) ;
126- if ( isReOpen ) {
127- this . iterateListeners ( ( cb ) => cb . databaseReOpened ?.( ) ) ;
128- }
129116 /**
130- * This is only required for the long-lived shared IndexedDB connections .
117+ * Execute opening of the db in a lock in order not to interfere with other operations .
131118 */
132- this . requiresHolds = ( this . _config as ResolvedWASQLiteOpenFactoryOptions ) . vfs == WASQLiteVFS . IDBBatchAtomicVFS ;
119+ return this . _acquireLock ( async ( ) => {
120+ // Dispose any previous table change listener.
121+ this . _disposeTableChangeListener ?.( ) ;
122+ this . _disposeTableChangeListener = null ;
123+
124+ const isReOpen = ! ! this . _db ;
125+
126+ this . _db = await this . options . openConnection ( ) ;
127+ await this . _db . init ( ) ;
128+ this . _config = await this . _db . getConfig ( ) ;
129+ await this . registerOnChangeListener ( this . _db ) ;
130+ if ( isReOpen ) {
131+ this . iterateListeners ( ( cb ) => cb . databaseReOpened ?.( ) ) ;
132+ }
133+ /**
134+ * This is only required for the long-lived shared IndexedDB connections.
135+ */
136+ this . requiresHolds = ( this . _config as ResolvedWASQLiteOpenFactoryOptions ) . vfs == WASQLiteVFS . IDBBatchAtomicVFS ;
137+ } ) ;
133138 }
134139
135140 protected _reOpen ( ) {
@@ -252,13 +257,10 @@ export class LockedAsyncDatabaseAdapter
252257 ) ;
253258 }
254259
255- protected async acquireLock ( callback : ( ) => Promise < any > , options ?: { timeoutMs ?: number } ) : Promise < any > {
256- await this . waitForInitialized ( ) ;
257-
260+ protected async _acquireLock ( callback : ( ) => Promise < any > , options ?: { timeoutMs ?: number } ) : Promise < any > {
258261 if ( this . closing ) {
259262 throw new Error ( `Cannot acquire lock, the database is closing` ) ;
260263 }
261-
262264 const abortController = new AbortController ( ) ;
263265 this . pendingAbortControllers . add ( abortController ) ;
264266 const { timeoutMs } = options ?? { } ;
@@ -278,36 +280,41 @@ export class LockedAsyncDatabaseAdapter
278280 if ( timeoutId ) {
279281 clearTimeout ( timeoutId ) ;
280282 }
281- let holdId : string | null = null ;
282- try {
283- // The database is being opened in the background. Wait for it here.
284- if ( this . databaseOpenPromise ) {
285- /**
286- * We can't await this since it uses the same lock as we're in now.
287- */
288- throw new ConnectionClosedError ( 'Connection is busy re-opening' ) ;
289- }
283+ return await callback ( ) ;
284+ }
285+ ) ;
286+ }
290287
291- holdId = this . requiresHolds ? await this . baseDB . markHold ( ) : null ;
292- return await callback ( ) ;
293- } catch ( ex ) {
294- if (
295- ex instanceof ConnectionClosedError ||
296- ( ex instanceof Error && ex . name === 'NoModificationAllowedError' )
297- ) {
298- if ( this . options . reOpenOnConnectionClosed && ! this . databaseOpenPromise && ! this . closing ) {
299- // Immediately re-open the database. We need to miss as little table updates as possible.
300- this . reOpenInternalDB ( ) ;
301- }
302- }
303- throw ex ;
304- } finally {
305- if ( holdId ) {
306- await this . baseDB . releaseHold ( holdId ) ;
288+ protected async acquireLock ( callback : ( ) => Promise < any > , options ?: { timeoutMs ?: number } ) : Promise < any > {
289+ await this . waitForInitialized ( ) ;
290+
291+ return this . _acquireLock ( async ( ) => {
292+ let holdId : string | null = null ;
293+ try {
294+ // The database is being opened in the background. Wait for it here.
295+ if ( this . databaseOpenPromise ) {
296+ /**
297+ * We can't await this since it uses the same lock as we're in now.
298+ */
299+ throw new ConnectionClosedError ( 'Connection is busy re-opening' ) ;
300+ }
301+
302+ holdId = this . requiresHolds ? await this . baseDB . markHold ( ) : null ;
303+ return await callback ( ) ;
304+ } catch ( ex ) {
305+ if ( ex instanceof ConnectionClosedError || ( ex instanceof Error && ex . name === 'NoModificationAllowedError' ) ) {
306+ if ( this . options . reOpenOnConnectionClosed && ! this . databaseOpenPromise && ! this . closing ) {
307+ // Immediately re-open the database. We need to miss as little table updates as possible.
308+ this . reOpenInternalDB ( ) ;
307309 }
308310 }
311+ throw ex ;
312+ } finally {
313+ if ( holdId ) {
314+ await this . baseDB . releaseHold ( holdId ) ;
315+ }
309316 }
310- ) ;
317+ } , options ) ;
311318 }
312319
313320 async readTransaction < T > ( fn : ( tx : Transaction ) => Promise < T > , options ?: DBLockOptions | undefined ) : Promise < T > {
0 commit comments