Skip to content

Commit b64b547

Browse files
committed
switch user back to pool default on connection release
1 parent 34a8c56 commit b64b547

File tree

5 files changed

+56
-9
lines changed

5 files changed

+56
-9
lines changed

Changes.md

+5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ This file is a manually maintained list of changes for each release. Feel free
44
to add your changes here when sending pull requests. Also send corrections if
55
you spot any mistakes.
66

7+
## NEXT_MINOR
8+
9+
* Pool resets credentials to pool configuration on returned connection
10+
instead of destroying after changeUser is called #837
11+
712
## v2.7.0 (2015-05-05)
813

914
* Destroy/end connections removed from the pool on error

Readme.md

+9-3
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ addition to those options pools accept a few extras:
390390

391391
### connection
392392

393-
The pool will emit a `connection` event when a new connection is made within the pool.
393+
The pool will emit a `connection` event when a new connection is made within the pool.
394394
If you need to set session variables on the connection before it gets used, you can
395395
listen to the `connection` event.
396396

@@ -459,7 +459,7 @@ poolCluster.getConnection('MASTER', function (err, connection) {});
459459
// Target Group : SLAVE1-2, Selector : order
460460
// If can't connect to SLAVE1, return SLAVE2. (remove SLAVE1 in the cluster)
461461
poolCluster.on('remove', function (nodeId) {
462-
console.log('REMOVED NODE : ' + nodeId); // nodeId = SLAVE1
462+
console.log('REMOVED NODE : ' + nodeId); // nodeId = SLAVE1
463463
});
464464

465465
poolCluster.getConnection('SLAVE*', 'ORDER', function (err, connection) {});
@@ -479,7 +479,7 @@ poolCluster.end(function (err) {
479479

480480
## PoolCluster Option
481481
* `canRetry`: If `true`, `PoolCluster` will attempt to reconnect when connection fails. (Default: `true`)
482-
* `removeNodeErrorCount`: If connection fails, node's `errorCount` increases.
482+
* `removeNodeErrorCount`: If connection fails, node's `errorCount` increases.
483483
When `errorCount` is greater than `removeNodeErrorCount`, remove a node in the `PoolCluster`. (Default: `5`)
484484
* `restoreNodeTimeout`: If connection fails, specifies the number of milliseconds
485485
before another connection attempt will be made. If set to `0`, then node will be
@@ -519,6 +519,12 @@ The available options for this feature are:
519519
A sometimes useful side effect of this functionality is that this function also
520520
resets any connection state (variables, transactions, etc.).
521521

522+
In the context of connection being returned to a Pool the connection will be
523+
reset back to the defaults for the pool before the connection is released to
524+
another `getConnection()` call. When this happens the pool will emit
525+
`connection` to give the listener a chance to setup state on the connection
526+
again since it will have been reset.
527+
522528
Errors encountered during this operation are treated as fatal connection errors
523529
by this module.
524530

lib/Pool.js

+28-2
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,11 @@ Pool.prototype.releaseConnection = function releaseConnection(connection) {
109109
}
110110

111111
if (connection._purge) {
112-
// purge connection from pool
113-
this._purgeConnection(connection);
112+
// restore the switched user
113+
this.restoreUser(connection, function (err) {
114+
if (err) return connection.destroy();
115+
connection._pool.releaseConnection(connection);
116+
});
114117
return;
115118
} else if (this._freeConnections.indexOf(connection) !== -1) {
116119
// connection already in free connection pool
@@ -247,6 +250,29 @@ Pool.prototype._removeConnection = function(connection) {
247250
this.releaseConnection(connection);
248251
};
249252

253+
Pool.prototype.restoreUser = function restoreUser(connection, callback) {
254+
var poolConfig = this.config.connectionConfig;
255+
var pool = this;
256+
257+
var config = connection.config;
258+
var user = poolConfig.user;
259+
var database = poolConfig.database;
260+
var password = poolConfig.password;
261+
262+
// only when credentials have been changed from the pool defaults
263+
if (config.user !== user || config.database !== database || config.password !== password) {
264+
connection.changeUser({ user: user, database: database, password: password }, function (err) {
265+
if (err) return callback(err);
266+
// emit as if it were a new connection so consumers can setup session state again
267+
pool.emit('connection', connection);
268+
callback(null);
269+
});
270+
connection._purge = false;
271+
} else {
272+
process.nextTick(callback);
273+
}
274+
}
275+
250276
Pool.prototype.escape = function(value) {
251277
return mysql.escape(value, this.config.connectionConfig.stringifyObjects, this.config.connectionConfig.timezone);
252278
};

lib/PoolConnection.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ inherits(PoolConnection, Connection);
88
function PoolConnection(pool, options) {
99
Connection.call(this, options);
1010
this._pool = pool;
11-
this._purge = false
11+
this._purge = false;
1212

1313
// When a fatal error occurs the connection's protocol ends, which will cause
1414
// the connection to end as well, thus we only need to watch for the end event
@@ -29,6 +29,7 @@ PoolConnection.prototype.changeUser = function changeUser(options, callback) {
2929

3030
PoolConnection.prototype.release = function release() {
3131
var pool = this._pool;
32+
var connection = this;
3233

3334
if (!pool || pool._closed) {
3435
return;

test/unit/pool/test-change-user-eject.js

+12-3
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,15 @@ var pool = common.createPool({
99
var closed = 0;
1010
var server = common.createFakeServer();
1111
var thread = 0;
12+
var connections = 0;
1213

1314
server.listen(common.fakeServerPort, function(err) {
1415
assert.ifError(err);
1516

17+
pool.on('connection', function(conn) {
18+
connections++;
19+
});
20+
1621
var conn0;
1722
var threadId;
1823
pool.getConnection(function(err, conn) {
@@ -22,6 +27,7 @@ server.listen(common.fakeServerPort, function(err) {
2227
threadId = conn.threadId;
2328
});
2429

30+
2531
pool.getConnection(function(err, conn) {
2632
assert.ifError(err);
2733
assert.ok(conn.threadId === 1 || conn.threadId === 2);
@@ -38,17 +44,20 @@ server.listen(common.fakeServerPort, function(err) {
3844

3945
pool.getConnection(function(err, conn1) {
4046
assert.ifError(err);
41-
assert.strictEqual(conn1.threadId, 3);
47+
assert.ok(conn1.threadId === 1 || conn1.threadId === 2);
48+
assert.strictEqual(conn1.config.user, 'user_1');
4249

4350
pool.getConnection(function(err, conn2) {
4451
assert.ifError(err);
45-
assert.strictEqual(conn2.threadId, threadId);
52+
assert.ok(conn2.threadId === 1 || conn2.threadId === 2);
53+
assert.strictEqual(conn1.config.user, 'user_1');
4654
conn1.release();
4755
conn2.release();
4856

4957
pool.end(function(err) {
5058
assert.ifError(err);
51-
assert.strictEqual(closed, 3);
59+
assert.strictEqual(connections, 3);
60+
assert.strictEqual(closed, 2);
5261
server.destroy();
5362
});
5463
});

0 commit comments

Comments
 (0)