diff --git a/Changes.md b/Changes.md index 452f4faff..57e0a41e1 100644 --- a/Changes.md +++ b/Changes.md @@ -7,6 +7,7 @@ you spot any mistakes. ## HEAD * Support Node.js 12.x #2211 +* Add `idleConnectionTimeout` to pool options ## v2.17.1 (2019-04-18) diff --git a/Readme.md b/Readme.md index 3d5069341..1d826b230 100644 --- a/Readme.md +++ b/Readme.md @@ -393,6 +393,9 @@ 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`) +* `idleConnectionTimeout`: The maximum number of milliseconds a connection can be + idle in the pool. If set to `0` connection will live until it is manually + destroyed or the pool is closed. (Default: `0`) ## Pool events diff --git a/lib/Pool.js b/lib/Pool.js index 87a40114a..40563ae2c 100644 --- a/lib/Pool.js +++ b/lib/Pool.js @@ -106,6 +106,11 @@ Pool.prototype.acquireConnection = function acquireConnection(connection, cb) { pool.emit('connection', connection); } + if (connection._idleTimeout) { + clearTimeout(connection._idleTimeout); + connection._idleTimeout = null; + } + pool.emit('acquire', connection); cb(null, connection); } diff --git a/lib/PoolConfig.js b/lib/PoolConfig.js index 8c5017a27..51f30b47f 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.idleConnectionTimeout = (options.idleConnectionTimeout === undefined) + ? 0 + : Number(options.idleConnectionTimeout); } PoolConfig.prototype.newConnectionConfig = function newConnectionConfig() { diff --git a/lib/PoolConnection.js b/lib/PoolConnection.js index 064c99d32..f3924aac6 100644 --- a/lib/PoolConnection.js +++ b/lib/PoolConnection.js @@ -5,6 +5,8 @@ var Events = require('events'); module.exports = PoolConnection; inherits(PoolConnection, Connection); +function _noop() {} + function PoolConnection(pool, options) { Connection.call(this, options); this._pool = pool; @@ -32,6 +34,13 @@ PoolConnection.prototype.release = function release() { return undefined; } + if (this._pool.config.idleConnectionTimeout) { + this._idleTimeout = setTimeout( + this._realEnd.bind(this, _noop), + this._pool.config.idleConnectionTimeout + ); + } + return pool.releaseConnection(this); }; @@ -58,6 +67,11 @@ PoolConnection.prototype._removeFromPool = function _removeFromPool() { return; } + if (this._idleTimeout) { + clearTimeout(this._idleTimeout); + this._idleTimeout = null; + } + var pool = this._pool; this._pool = null; diff --git a/test/unit/pool/test-idle-connection-timeout.js b/test/unit/pool/test-idle-connection-timeout.js new file mode 100644 index 000000000..49df581a6 --- /dev/null +++ b/test/unit/pool/test-idle-connection-timeout.js @@ -0,0 +1,38 @@ +var assert = require('assert'); +var common = require('../../common'); +var pool = common.createPool({ + port : common.fakeServerPort, + idleConnectionTimeout : 100 +}); + +var server = common.createFakeServer(); + +server.listen(common.fakeServerPort, function(err){ + assert.ifError(err); + + pool.once('release', function(connection) { + assert.ok(connection); + setTimeout(function() { + assert.equal(connection.state, 'disconnected'); + pool.end(function (err) { + assert.ifError(err); + server.destroy(); + }); + }, 200); + }); + + pool.getConnection(function (err, firstConnection) { + assert.ifError(err); + assert.ok(firstConnection); + setTimeout(function() { + pool.getConnection(function (err, connection) { + assert.ifError(err); + assert.equal(connection.state, 'authenticated'); + assert.equal(connection._idleTimeout, null); + assert.equal(firstConnection, connection); + connection.release(); + }); + }, 75); + firstConnection.release(); + }); +});