Skip to content

Commit 1e3cf9b

Browse files
committed
fix(pool): getConnection callback should be called only once
1 parent a97ff42 commit 1e3cf9b

File tree

4 files changed

+107
-62
lines changed

4 files changed

+107
-62
lines changed

lib/pool.js

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class Pool extends EventEmitter {
5656
config: this.config.connectionConfig
5757
});
5858
this._allConnections.push(connection);
59-
return connection.connect(err => {
59+
return connection.connect((err) => {
6060
if (this._closed) {
6161
return cb(new Error('Pool is closed.'));
6262
}
@@ -80,21 +80,20 @@ class Pool extends EventEmitter {
8080
this.emit('enqueue');
8181

8282
if (this.config.acquireTimeout > 0) {
83+
// eslint-disable-next-line prefer-const
84+
let timer;
8385

84-
const timeout = setTimeout(() => {
86+
const wrappedCb = (err, connection) => {
87+
clearTimeout(timer);
88+
cb(err, connection);
89+
};
8590

86-
spliceConnection(this._connectionQueue, cb);
91+
timer = setTimeout(() => {
92+
spliceConnection(this._connectionQueue, wrappedCb);
8793
cb(new Error('Timeout acquiring connection'));
88-
8994
}, this.config.acquireTimeout);
9095

91-
return this._connectionQueue.push((err, connection) => {
92-
93-
clearTimeout(timeout);
94-
95-
cb(err, connection);
96-
97-
}, this.config.acquireTimeout);
96+
return this._connectionQueue.push(wrappedCb);
9897
}
9998

10099
return this._connectionQueue.push(cb);
@@ -121,7 +120,7 @@ class Pool extends EventEmitter {
121120
this._closed = true;
122121
clearTimeout(this._removeIdleTimeoutConnectionsTimer);
123122
if (typeof cb !== 'function') {
124-
cb = function(err) {
123+
cb = function (err) {
125124
if (err) {
126125
throw err;
127126
}
@@ -130,7 +129,7 @@ class Pool extends EventEmitter {
130129
let calledBack = false;
131130
let closedConnections = 0;
132131
let connection;
133-
const endCB = function(err) {
132+
const endCB = function (err) {
134133
if (calledBack) {
135134
return;
136135
}
@@ -158,7 +157,8 @@ class Pool extends EventEmitter {
158157
this.config.connectionConfig
159158
);
160159
if (typeof cmdQuery.namedPlaceholders === 'undefined') {
161-
cmdQuery.namedPlaceholders = this.config.connectionConfig.namedPlaceholders;
160+
cmdQuery.namedPlaceholders =
161+
this.config.connectionConfig.namedPlaceholders;
162162
}
163163
this.getConnection((err, conn) => {
164164
if (err) {

test/integration/promise-wrappers/test-promise-wrappers.test.cjs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,52 @@ function testErrors() {
7575
});
7676
}
7777

78+
function testPoolAcquireTimeout() {
79+
80+
(async () => {
81+
const ACQUIRE_TIMEOUT = 500;
82+
const pool = createPool({
83+
...config,
84+
connectionLimit: 2,
85+
acquireTimeout: ACQUIRE_TIMEOUT,
86+
});
87+
88+
const c1 = await pool.getConnection();
89+
90+
assert.ok(c1);
91+
92+
const c2 = await pool.getConnection();
93+
94+
assert.ok(c2);
95+
96+
const c3StartedAt = Date.now();
97+
try {
98+
99+
await pool.getConnection();
100+
assert.fail('should not reach here');
101+
}
102+
catch (e) {
103+
104+
assert.equal(Date.now() - c3StartedAt >= ACQUIRE_TIMEOUT, true);
105+
assert.equal(e.message, 'Timeout acquiring connection');
106+
}
107+
108+
c2.release();
109+
110+
const c4 = await pool.getConnection();
111+
112+
c1.release();
113+
c4.release();
114+
115+
await pool.end();
116+
117+
assert.ok(c4, 'acquireTimeout is working correctly');
118+
119+
})().catch((err) => {
120+
assert.fail(err);
121+
});
122+
}
123+
78124
function testObjParams() {
79125
let connResolved;
80126
createConnection(config)
@@ -473,6 +519,7 @@ testChangeUser();
473519
testConnectionProperties();
474520
testPoolConnectionDestroy();
475521
testPromiseLibrary();
522+
testPoolAcquireTimeout();
476523

477524
process.on('exit', () => {
478525
assert.equal(doneCalled, true, 'done not called');

test/integration/test-pool-acquire-timeout.js

Lines changed: 0 additions & 48 deletions
This file was deleted.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
'use strict';
2+
3+
const mysql = require('../..');
4+
const assert = require('assert');
5+
const common = require('../common.test.cjs');
6+
7+
const poolConfig = common.getConfig();
8+
9+
const ACQUIRE_TIMEOUT = 500;
10+
const pool = new mysql.createPool({
11+
...poolConfig,
12+
acquireTimeout: ACQUIRE_TIMEOUT,
13+
connectionLimit: 2
14+
});
15+
16+
pool.getConnection((err, c1) => {
17+
assert.equal(!!c1, true);
18+
assert.ifError(err);
19+
20+
pool.getConnection((err, c2) => {
21+
assert.ifError(err);
22+
assert.equal(!!c2, true);
23+
24+
const C3_STARTED_AT = Date.now();
25+
26+
pool.getConnection((e3, c3) => {
27+
const C3_DONE_AT = Date.now();
28+
assert.equal(C3_DONE_AT - C3_STARTED_AT >= ACQUIRE_TIMEOUT, true);
29+
assert.equal(C3_DONE_AT - C3_STARTED_AT < ACQUIRE_TIMEOUT * 2, true);
30+
31+
assert.notEqual(e3, null);
32+
assert.equal(e3.message, 'Timeout acquiring connection', 'Acquire timeout error message is correct');
33+
assert.equal(!c3, true);
34+
c1.release();
35+
36+
pool.getConnection((e4, c4) => {
37+
assert.equal(e4, null);
38+
assert.equal(!!c4, true);
39+
40+
c4.release();
41+
c2.release();
42+
pool.end();
43+
});
44+
});
45+
});
46+
});

0 commit comments

Comments
 (0)