Skip to content

Commit 186a4fd

Browse files
committed
feat: auto purge stale prepared statements from cache and retry query
1 parent 2b5fe52 commit 186a4fd

2 files changed

Lines changed: 74 additions & 1 deletion

File tree

lib/base/connection.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,9 @@ class BaseConnection extends EventEmitter {
836836
return false;
837837
}
838838

839+
// In this case there currently will not be any other events emitted before 'end', but leaving
840+
// this here in case that changes in the future...
841+
/* c8 ignore next */
839842
return origEmit(eventName, ...rest);
840843
};
841844

@@ -889,6 +892,9 @@ class BaseConnection extends EventEmitter {
889892
return false;
890893
}
891894

895+
// In this case there currently will not be any other events emitted before 'end', but leaving
896+
// this here in case that changes in the future...
897+
/* c8 ignore next */
892898
return origEmit(eventName, ...rest);
893899
};
894900

test/integration/connection/test-execute-cached.test.mts

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ await describe('Execute Cached', async () => {
4141
strict.deepEqual(rows3, [{ test: 126 }]);
4242
});
4343

44-
await it('should discard cached prepared statements that no longer exist on the server and retry automatically', async () => {
44+
await it('should discard cached prepared statements that no longer exist on the server and retry automatically (Callback API)', async () => {
4545
// Remove on the server but leave it in the cache
4646
// @ts-expect-error: internal access
4747
connection._statements.get(key).close();
@@ -59,6 +59,7 @@ await describe('Execute Cached', async () => {
5959
// @ts-expect-error: internal access
6060
strict(connection._statements.get(key).id === oldStatementId);
6161

62+
// Callback API
6263
const rows1 = await new Promise<TestRow[]>((resolve, reject) => {
6364
connection.execute<TestRow[]>(q, [123], (err, _rows) =>
6465
err ? reject(err) : resolve(_rows)
@@ -71,6 +72,7 @@ await describe('Execute Cached', async () => {
7172
);
7273
});
7374

75+
// EventEmitter API
7476
const rows3 = await new Promise<TestRow[]>((resolve, reject) => {
7577
connection.execute<TestRow[]>(q, [125], (err, _rows) =>
7678
err ? reject(err) : resolve(_rows)
@@ -91,5 +93,70 @@ await describe('Execute Cached', async () => {
9193
strict.deepEqual(rows3, [{ test: 126 }]);
9294
});
9395

96+
await it('should discard cached prepared statements that no longer exist on the server and retry automatically (EventEmitter API)', async () => {
97+
// Remove on the server but leave it in the cache
98+
// @ts-expect-error: internal access
99+
connection._statements.get(key).close();
100+
101+
// Remember the id
102+
// @ts-expect-error: internal access
103+
const { id: oldStatementId } = connection._statements.get(key);
104+
105+
// @ts-expect-error: internal access
106+
strict(connection._statements.size === 1);
107+
// @ts-expect-error: internal access
108+
strict(connection._statements.get(key).query === q);
109+
// @ts-expect-error: internal access
110+
strict(connection._statements.get(key).parameters.length === 1);
111+
// @ts-expect-error: internal access
112+
strict(connection._statements.get(key).id === oldStatementId);
113+
114+
const rows1 = await new Promise<TestRow[]>((resolve, reject) => {
115+
const executeCommand = connection.execute<TestRow[]>(q, [123]);
116+
const _rows = [];
117+
118+
executeCommand.once('error', (err) => reject(err));
119+
executeCommand.on('result', (row) => {
120+
_rows.push(row);
121+
});
122+
executeCommand.once('end', () => resolve(_rows));
123+
});
124+
125+
const rows2 = await new Promise<TestRow[]>((resolve, reject) => {
126+
const executeCommand = connection.execute<TestRow[]>(q, [124]);
127+
const _rows = [];
128+
129+
executeCommand.once('error', (err) => reject(err));
130+
executeCommand.on('result', (row) => {
131+
_rows.push(row);
132+
});
133+
executeCommand.once('end', () => resolve(_rows));
134+
});
135+
136+
const rows3 = await new Promise<TestRow[]>((resolve, reject) => {
137+
const executeCommand = connection.execute<TestRow[]>(q, [125]);
138+
const _rows = [];
139+
140+
executeCommand.once('error', (err) => reject(err));
141+
executeCommand.on('result', (row) => {
142+
_rows.push(row);
143+
});
144+
executeCommand.once('end', () => resolve(_rows));
145+
});
146+
147+
// @ts-expect-error: internal access
148+
strict(connection._statements.size === 1);
149+
// @ts-expect-error: internal access
150+
strict(connection._statements.get(key).query === q);
151+
// @ts-expect-error: internal access
152+
strict(connection._statements.get(key).parameters.length === 1);
153+
// @ts-expect-error: internal access
154+
strict(connection._statements.get(key).id !== oldStatementId);
155+
156+
strict.deepEqual(rows1, [{ test: 124 }]);
157+
strict.deepEqual(rows2, [{ test: 125 }]);
158+
strict.deepEqual(rows3, [{ test: 126 }]);
159+
});
160+
94161
connection.end();
95162
});

0 commit comments

Comments
 (0)