Skip to content

Commit 70340d5

Browse files
cleanup closed logic
1 parent 4b55ed4 commit 70340d5

File tree

2 files changed

+23
-30
lines changed

2 files changed

+23
-30
lines changed

src/DBListenerManager.ts

+2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ export interface DBListener extends BaseListener {
3939
* is started, committed or rolled back.
4040
*/
4141
writeTransaction: (event: WriteTransactionEvent) => void;
42+
43+
closed: () => void;
4244
}
4345

4446
export class DBListenerManager extends BaseObserver<DBListener> {}

src/setup-open.ts

+21-30
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,11 @@ const getRequestId = () => {
3939
const LockCallbacks: Record<ContextLockID, LockCallbackRecord> = {};
4040
let 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
*/
5045
function 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

Comments
 (0)