diff --git a/Readme.md b/Readme.md index 4f52089f2..6828c21db 100644 --- a/Readme.md +++ b/Readme.md @@ -369,7 +369,7 @@ time one is needed. Connections are lazily created by the pool. If you configure the pool to allow up to 100 connections, but only ever use 5 simultaneously, only 5 connections will be made. Connections are also cycled round-robin style, with connections -being taken from the top of the pool and returning to the bottom. +being taken from the top of the pool and returning to the bottom. If you want to change cycle strategy, you can set `stackCycle` option in pool options. When a previous connection is retrieved from the pool, a ping packet is sent to the server to check if the connection is still good. @@ -392,6 +392,7 @@ constructor. In addition to those options pools accept a few extras: * `queueLimit`: The maximum number of connection requests the pool will queue before returning an error from `getConnection`. If set to `0`, there is no limit to the number of queued connection requests. (Default: `0`) +* `stackCycle`: Determines how the released connections rotates. If `true`, It's cycled stack style. If you need to disconnect a useless connection after suddenly an increase in connection, use the stack strategy. If `false`, It's cycled round-robin style. (Default: `false`) ## Pool events diff --git a/lib/Pool.js b/lib/Pool.js index 87a40114a..5b149cb2a 100644 --- a/lib/Pool.js +++ b/lib/Pool.js @@ -137,8 +137,12 @@ Pool.prototype.releaseConnection = function releaseConnection(connection) { // this won't catch all double-release cases throw new Error('Connection already released'); } else { - // add connection to end of free queue - this._freeConnections.push(connection); + if (this.config.stackCycle) { + this._freeConnections.unshift(connection); + } else { + // add connection to end of free queue + this._freeConnections.push(connection); + } this.emit('release', connection); } } diff --git a/lib/PoolConfig.js b/lib/PoolConfig.js index 8c5017a27..480c9338a 100644 --- a/lib/PoolConfig.js +++ b/lib/PoolConfig.js @@ -20,6 +20,9 @@ function PoolConfig(options) { this.queueLimit = (options.queueLimit === undefined) ? 0 : Number(options.queueLimit); + this.stackCycle = (options.stackCycle === undefined) + ? false + : Boolean(options.stackCycle); } PoolConfig.prototype.newConnectionConfig = function newConnectionConfig() { diff --git a/test/unit/pool/test-connection-stack-cycle.js b/test/unit/pool/test-connection-stack-cycle.js new file mode 100644 index 000000000..5237f9908 --- /dev/null +++ b/test/unit/pool/test-connection-stack-cycle.js @@ -0,0 +1,46 @@ +var assert = require('assert'); +var common = require('../../common'); +var pool = common.createPool({ + connectionLimit : 2, + port : common.fakeServerPort, + stackCycle : true +}); + +var server = common.createFakeServer(); + +server.listen(common.fakeServerPort, function (err) { + assert.ifError(err); + + var releasedThreadId = null; + var releaseCount = 0; + + pool.on('release', function (connection) { + releaseCount++; + releasedThreadId = connection.threadId; + }); + + pool.getConnection(function (err, firstConnection) { + assert.ifError(err); + assert.ok(firstConnection); + + pool.getConnection(function (err, secondConnection) { + assert.ifError(err); + assert.ok(secondConnection); + firstConnection.release(); + secondConnection.release(); + assert.equal(releaseCount, 2); + assert.equal(releasedThreadId, secondConnection.threadId); + + pool.getConnection(function (err, recycledConnection) { + assert.ifError(err); + assert.ok(recycledConnection); + assert.equal(recycledConnection.threadId, releasedThreadId); + + pool.end(function (err) { + assert.ifError(err); + server.destroy(); + }); + }); + }); + }); +});