Skip to content

Commit 5ea649d

Browse files
committed
Ensure pool.getConnection retrieves good connections
fixes #434 fixes #557 fixes #778
1 parent d6f6d23 commit 5ea649d

File tree

5 files changed

+80
-3
lines changed

5 files changed

+80
-3
lines changed

Changes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ you spot any mistakes.
1818
* Fix `pool.releaseConnection` to keep connection queue flowing #797
1919
* Fix SSL handshake error to be catchable #800
2020
* Add `connection.threadId` to get MySQL connection ID #602
21+
* Ensure `pool.getConnection` retrieves good connections #434 #557 #778
2122

2223
## v2.1.1 (2014-03-13)
2324

Readme.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,9 @@ up to 100 connections, but only ever use 5 simultaneously, only 5 connections
304304
will be made. Connections are also cycled round-robin style, with connections
305305
being taken from the top of the pool and returning to the bottom.
306306

307+
When a previous connection is retrieved from the pool, a ping packet is sent
308+
to the server to check if the connection is still good.
309+
307310
## Pool options
308311

309312
Pools accept all the same options as a connection. When creating a new

lib/Pool.js

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,7 @@ Pool.prototype.getConnection = function (cb) {
3131
if (this._freeConnections.length > 0) {
3232
connection = this._freeConnections.shift();
3333

34-
return process.nextTick(function(){
35-
cb(null, connection);
36-
});
34+
return this.acquireConnection(connection, cb);
3735
}
3836

3937
if (this.config.connectionLimit === 0 || this._allConnections.length < this.config.connectionLimit) {
@@ -69,6 +67,27 @@ Pool.prototype.getConnection = function (cb) {
6967
this._connectionQueue.push(cb);
7068
};
7169

70+
Pool.prototype.acquireConnection = function acquireConnection(connection, cb) {
71+
if (connection._pool !== this) {
72+
throw new Error('Connection acquired from wrong pool.');
73+
}
74+
75+
var pool = this;
76+
77+
connection._pool = null;
78+
connection.ping(function(err){
79+
if (!err) {
80+
connection._pool = pool;
81+
cb(null, connection);
82+
return;
83+
}
84+
85+
connection.destroy();
86+
pool._connectionQueue.unshift(cb);
87+
pool._removeConnection(connection);
88+
});
89+
};
90+
7291
Pool.prototype.releaseConnection = function releaseConnection(connection) {
7392
var cb;
7493

test/FakeServer.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@ FakeConnection.prototype._parsePacket = function(header) {
131131
case Packets.ComQueryPacket:
132132
this.emit('query', packet);
133133
break;
134+
case Packets.ComPingPacket:
135+
this._sendPacket(new Packets.OkPacket());
136+
this._parser.resetPacketNumber();
137+
break;
134138
case Packets.ComQuitPacket:
135139
this.emit('quit', packet);
136140
this._socket.end();
@@ -151,6 +155,7 @@ FakeConnection.prototype._determinePacket = function() {
151155
switch (firstByte) {
152156
case 0x01: return Packets.ComQuitPacket;
153157
case 0x03: return Packets.ComQueryPacket;
158+
case 0x0e: return Packets.ComPingPacket;
154159
default:
155160
throw new Error('Unknown packet, first byte: ' + firstByte);
156161
break;
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
var assert = require('assert');
2+
var common = require('../../common');
3+
var pool = common.createPool({
4+
connectionLimit : 1,
5+
port : common.fakeServerPort
6+
});
7+
var server = common.createFakeServer();
8+
9+
var seq = 0;
10+
var serverConn = null;
11+
var tid = 0;
12+
13+
server.listen(common.fakeServerPort, function(err){
14+
assert.ifError(err);
15+
16+
pool.getConnection(function(err, conn){
17+
assert.ifError(err);
18+
assert.equal(conn.threadId, 1);
19+
conn.release();
20+
21+
// server destroys connection in pool
22+
// read ECONNRESET
23+
serverConn.destroy();
24+
25+
pool.getConnection(function(err, conn){
26+
assert.ifError(err);
27+
assert.equal(++seq, 1);
28+
assert.equal(conn.threadId, 2);
29+
conn.ping(function(err){
30+
assert.ifError(err);
31+
conn.release();
32+
});
33+
});
34+
35+
pool.getConnection(function(err, conn){
36+
assert.ifError(err);
37+
assert.equal(++seq, 2);
38+
assert.equal(conn.threadId, 2);
39+
server.destroy();
40+
});
41+
});
42+
});
43+
44+
server.on('connection', function(incomingConnection) {
45+
serverConn = incomingConnection;
46+
incomingConnection.handshake({
47+
threadId: ++tid
48+
});
49+
});

0 commit comments

Comments
 (0)