@@ -39,16 +39,11 @@ const getRequestId = () => {
3939const LockCallbacks : Record < ContextLockID , LockCallbackRecord > = { } ;
4040let proxy : ISQLite ;
4141
42- /**
43- * Creates a unique identifier for all a database's lock requests
44- */
45- const lockKey = ( dbName : string , id : ContextLockID ) => `${ dbName } :${ id } ` ;
46-
4742/**
4843 * Closes the context in JS and C++
4944 */
5045function closeContextLock ( dbName : string , id : ContextLockID ) {
51- delete LockCallbacks [ lockKey ( dbName , id ) ] ;
46+ delete LockCallbacks [ id ] ;
5247
5348 // This is configured by the setupOpen function
5449 proxy . releaseLock ( dbName , id ) ;
@@ -64,10 +59,9 @@ global.onLockContextIsAvailable = async (dbName: string, lockId: ContextLockID)
6459 // Don't hold C++ bridge side up waiting to complete
6560 setImmediate ( async ( ) => {
6661 try {
67- const key = lockKey ( dbName , lockId ) ;
68- const record = LockCallbacks [ key ] ;
62+ const record = LockCallbacks [ lockId ] ;
6963 // clear record after fetching, the hash should only contain pending requests
70- delete LockCallbacks [ key ] ;
64+ delete LockCallbacks [ lockId ] ;
7165
7266 if ( record ?. timeout ) {
7367 clearTimeout ( record . timeout ) ;
@@ -125,10 +119,21 @@ export function setupOpen(QuickSQLite: ISQLite) {
125119 // Wrap the callback in a promise that will resolve to the callback result
126120 return new Promise < T > ( ( resolve , reject ) => {
127121 // Add callback to the queue for timing
128- const key = lockKey ( dbName , id ) ;
129- const record = ( LockCallbacks [ key ] = {
122+ const closedListener = listenerManager . registerListener ( {
123+ closed : ( ) => {
124+ closedListener ?.( ) ;
125+ // Remove callback from the queue
126+ delete LockCallbacks [ id ] ;
127+ // Reject the lock request if the connection is closed
128+ reject ( new Error ( 'Connection is closed' ) ) ;
129+ }
130+ } ) ;
131+
132+ const record = ( LockCallbacks [ id ] = {
130133 callback : async ( context : LockContext ) => {
131134 try {
135+ // Remove the close listener
136+ closedListener ?.( ) ;
132137 await hooks ?. lockAcquired ?.( ) ;
133138 const res = await callback ( context ) ;
134139 closeContextLock ( dbName , id ) ;
@@ -149,13 +154,14 @@ export function setupOpen(QuickSQLite: ISQLite) {
149154 if ( timeout ) {
150155 record . timeout = setTimeout ( ( ) => {
151156 // The callback won't be executed
152- delete LockCallbacks [ key ] ;
157+ delete LockCallbacks [ id ] ;
153158 reject ( new Error ( `Lock request timed out after ${ timeout } ms` ) ) ;
154159 } , timeout ) ;
155160 }
156161 } catch ( ex ) {
162+ closedListener ?.( ) ;
157163 // Remove callback from the queue
158- delete LockCallbacks [ key ] ;
164+ delete LockCallbacks [ id ] ;
159165 reject ( ex ) ;
160166 }
161167 } ) ;
@@ -236,23 +242,8 @@ export function setupOpen(QuickSQLite: ISQLite) {
236242 return {
237243 close : ( ) => {
238244 QuickSQLite . close ( dbName ) ;
239- // Reject any pending lock requests
240- Object . entries ( LockCallbacks ) . forEach ( ( [ key , record ] ) => {
241- const recordDBName = key . split ( ':' ) [ 0 ] ;
242- if ( dbName !== recordDBName ) {
243- return ;
244- }
245- // A bit of a hack, let the callbacks run with an execute method that will fail
246- record
247- . callback ( {
248- execute : async ( ) => {
249- throw new Error ( 'Connection is closed' ) ;
250- }
251- } )
252- . catch ( ( ) => { } ) ;
253-
254- delete LockCallbacks [ key ] ;
255- } ) ;
245+ // Close any pending listeners
246+ listenerManager . iterateListeners ( ( l ) => l . closed ?.( ) ) ;
256247 } ,
257248 refreshSchema : ( ) => QuickSQLite . refreshSchema ( dbName ) ,
258249 execute : ( sql : string , args ?: any [ ] ) => writeLock ( ( context ) => context . execute ( sql , args ) ) ,
0 commit comments