Skip to content

Commit 48263cd

Browse files
yamnighMichael Nighgajus
authored
fix: release pending pool connections on error (#632)
* release pending pool connections on error * changeset * simplify try/catch * oops - remove package-lock.json --------- Co-authored-by: Michael Nigh <[email protected]> Co-authored-by: Gajus Kuizinas <[email protected]>
1 parent c415b16 commit 48263cd

File tree

4 files changed

+60
-2
lines changed

4 files changed

+60
-2
lines changed

.changeset/metal-clocks-guess.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"slonik": patch
3+
---
4+
5+
Fix: release pending pool connections on error

packages/slonik/src/factories/createConnectionPool.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,10 @@ export const createConnectionPool = ({
139139

140140
pendingConnections.push(pendingConnection);
141141

142-
const connection = await pendingConnection;
142+
const connection = await pendingConnection.catch((error) => {
143+
pendingConnections.pop();
144+
throw error;
145+
});
143146

144147
const onRelease = () => {
145148
const waitingClient = waitingClients.shift();
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/* eslint-disable no-console */
2+
3+
import { createPool, sql } from '..';
4+
import { startTestContainer } from './termination.test';
5+
import test from 'ava';
6+
import { execSync } from 'node:child_process';
7+
8+
/**
9+
* @see https://github.com/gajus/slonik/issues/631
10+
*/
11+
test('releases failed connections', async (t) => {
12+
t.timeout(10_000);
13+
14+
try {
15+
const output = execSync('docker --version', { encoding: 'utf8' });
16+
console.log('Docker CLI is available:', output.trim());
17+
} catch {
18+
console.log('Skipper the test. Docker CLI is not available.');
19+
20+
return;
21+
}
22+
23+
const { dsn, terminate } = await startTestContainer();
24+
25+
const pool = await createPool(dsn, {
26+
connectionRetryLimit: 1,
27+
connectionTimeout: 500,
28+
maximumPoolSize: 1,
29+
});
30+
31+
terminate();
32+
33+
const isConnectionAvailable = async () => {
34+
try {
35+
await pool.connect((connection) => {
36+
return connection.oneFirst(sql.unsafe`SELECT NOW()`);
37+
});
38+
return true;
39+
} catch {
40+
// do nothing
41+
}
42+
43+
return false;
44+
};
45+
46+
t.deepEqual(
47+
[await isConnectionAvailable(), await isConnectionAvailable()],
48+
[false, false],
49+
);
50+
});

packages/slonik/src/integration.test/termination.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { execSync, spawn } from 'node:child_process';
77
import { randomUUID } from 'node:crypto';
88
import { setTimeout } from 'node:timers/promises';
99

10-
const startTestContainer = async () => {
10+
export const startTestContainer = async () => {
1111
const dockerContainerName = `slonik-test-${randomUUID()}`;
1212
const servicePort = await getPort();
1313

0 commit comments

Comments
 (0)