From 5df4925abf8c8b0d779928d47f3270392de5d8af Mon Sep 17 00:00:00 2001 From: HQidea Date: Sun, 27 Aug 2017 22:32:24 +0800 Subject: [PATCH 1/5] feat: pool adds gracefulExit to end gracefully --- .gitignore | 1 + Readme.md | 6 +++ lib/Pool.js | 45 +++++++++++++++----- lib/PoolConfig.js | 3 ++ test/unit/pool/test-graceful-exit-ping.js | 46 +++++++++++++++++++++ test/unit/pool/test-graceful-exit-queued.js | 37 +++++++++++++++++ 6 files changed, 128 insertions(+), 10 deletions(-) create mode 100644 test/unit/pool/test-graceful-exit-ping.js create mode 100644 test/unit/pool/test-graceful-exit-queued.js diff --git a/.gitignore b/.gitignore index cfdb519e7..7ffbc5752 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ coverage/ node_modules/ npm-debug.log +.DS_Store diff --git a/Readme.md b/Readme.md index f9e2000aa..f2b12c323 100644 --- a/Readme.md +++ b/Readme.md @@ -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`) +* `gracefulExit`: Determines whether to end gracefully. If `true`, every `pool.getConnection` or `pool.query` called before `pool.end` will success. If `false`, only commands / queries already in progress will complete, others will throw an error. ## Pool events @@ -462,6 +463,11 @@ all the connections have ended. **Once `pool.end()` has been called, `pool.getConnection` and other operations can no longer be performed** +If `gracefulExit` is set to `true`, the connections end _gracefully_, so all + -pending queries will still complete and the time to end the pool will vary. + +The default `gracefulExit` is `false`, the following behavior will take effect. + This works by calling `connection.end()` on every active connection in the pool, which queues a `QUIT` packet on the connection. And sets a flag to prevent `pool.getConnection` from continuing to create any new connections. diff --git a/lib/Pool.js b/lib/Pool.js index 87a40114a..e7a3875eb 100644 --- a/lib/Pool.js +++ b/lib/Pool.js @@ -17,9 +17,10 @@ function Pool(options) { this._freeConnections = []; this._connectionQueue = []; this._closed = false; + this._pendingClosing = false; } -Pool.prototype.getConnection = function (cb) { +Pool.prototype.getConnection = function (cb, queued) { if (this._closed) { var err = new Error('Pool is closed.'); @@ -33,12 +34,21 @@ Pool.prototype.getConnection = function (cb) { var connection; var pool = this; - if (this._freeConnections.length > 0) { + if (this._freeConnections.length > 0 && (!this._pendingClosing || queued)) { connection = this._freeConnections.shift(); this.acquireConnection(connection, cb); return; } + if (this._pendingClosing) { + var err = new Error('Pool is closed.'); + err.code = 'POOL_CLOSED'; + process.nextTick(function () { + cb(err); + }); + return; + } + if (this.config.connectionLimit === 0 || this._allConnections.length < this.config.connectionLimit) { connection = new PoolConnection(this, { config: this.config.newConnectionConfig() }); @@ -141,6 +151,10 @@ Pool.prototype.releaseConnection = function releaseConnection(connection) { this._freeConnections.push(connection); this.emit('release', connection); } + + if (this._pendingClosing) { + this.end(this._endCallback); + } } if (this._closed) { @@ -154,19 +168,18 @@ Pool.prototype.releaseConnection = function releaseConnection(connection) { }); } else if (this._connectionQueue.length) { // get connection with next waiting callback - this.getConnection(this._connectionQueue.shift()); + this.getConnection(this._connectionQueue.shift(), true); } }; Pool.prototype.end = function (cb) { - this._closed = true; - if (typeof cb !== 'function') { cb = function (err) { if (err) throw err; }; } + var readyToEnd = false; var calledBack = false; var waitingClose = 0; @@ -177,14 +190,26 @@ Pool.prototype.end = function (cb) { } } - while (this._allConnections.length !== 0) { - waitingClose++; - this._purgeConnection(this._allConnections[0], onEnd); + if (this._acquiringConnections.length === 0 && this._connectionQueue.length === 0) { + readyToEnd = true; } - if (waitingClose === 0) { - process.nextTick(onEnd); + if (!this.config.gracefulExit || readyToEnd) { + this._closed = true; + + while (this._allConnections.length !== 0) { + waitingClose++; + this._purgeConnection(this._allConnections[0], onEnd); + } + + if (waitingClose === 0) { + process.nextTick(onEnd); + } + return; } + + this._pendingClosing = true; + this._endCallback = cb; }; Pool.prototype.query = function (sql, values, cb) { diff --git a/lib/PoolConfig.js b/lib/PoolConfig.js index 8c5017a27..b25c6dd9c 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.gracefulExit = (options.gracefulExit === undefined) + ? false + : Boolean(options.gracefulExit); } PoolConfig.prototype.newConnectionConfig = function newConnectionConfig() { diff --git a/test/unit/pool/test-graceful-exit-ping.js b/test/unit/pool/test-graceful-exit-ping.js new file mode 100644 index 000000000..1d7d8e794 --- /dev/null +++ b/test/unit/pool/test-graceful-exit-ping.js @@ -0,0 +1,46 @@ +var common = require('../../common'); +var assert = require('assert'); +var pool = common.createPool({ + connectionLimit : 1, + port : common.fakeServerPort, + queueLimit : 5, + waitForConnections : true, + gracefulExit : true +}); + +var server = common.createFakeServer(); + +server.listen(common.fakeServerPort, function (err) { + assert.ifError(err); + + pool.getConnection(function (err, conn) { + assert.ifError(err); + conn.release(); + + pool.getConnection(function (err, conn) { + assert.ifError(err); + conn.release(); + }); + + pool.end(function (err) { + assert.ifError(err); + server.destroy(); + }); + + pool.getConnection(function (err) { + assert.ok(err); + assert.equal(err.message, 'Pool is closed.'); + assert.equal(err.code, 'POOL_CLOSED'); + }); + }); +}); + +server.on('connection', function (conn) { + conn.handshake(); + conn.on('ping', function () { + setTimeout(function () { + conn._sendPacket(new common.Packets.OkPacket()); + conn._parser.resetPacketNumber(); + }, 100); + }); +}); diff --git a/test/unit/pool/test-graceful-exit-queued.js b/test/unit/pool/test-graceful-exit-queued.js new file mode 100644 index 000000000..43927e195 --- /dev/null +++ b/test/unit/pool/test-graceful-exit-queued.js @@ -0,0 +1,37 @@ +var common = require('../../common'); +var assert = require('assert'); +var pool = common.createPool({ + connectionLimit : 1, + port : common.fakeServerPort, + queueLimit : 5, + waitForConnections : true, + gracefulExit : true +}); + +var server = common.createFakeServer(); + +server.listen(common.fakeServerPort, function (err) { + assert.ifError(err); + + pool.getConnection(function (err, conn) { + assert.ifError(err); + + pool.end(function (err) { + assert.ifError(err); + server.destroy(); + }); + + pool.getConnection(function (err) { + assert.ok(err); + assert.equal(err.message, 'Pool is closed.'); + assert.equal(err.code, 'POOL_CLOSED'); + }); + + conn.release(); + }); + + pool.getConnection(function (err, conn) { + assert.ifError(err); + conn.release(); + }); +}); From f39bce5a6b955e38026548d134d4fc32462eb377 Mon Sep 17 00:00:00 2001 From: HQidea Date: Sat, 9 Sep 2017 15:30:55 +0800 Subject: [PATCH 2/5] chore: gracefulExit is given to pool.end --- .gitignore | 1 - Readme.md | 31 ++++++++++++++------- lib/Pool.js | 20 +++++++------ lib/PoolConfig.js | 3 -- test/unit/pool/test-graceful-exit-ping.js | 5 ++-- test/unit/pool/test-graceful-exit-queued.js | 5 ++-- 6 files changed, 37 insertions(+), 28 deletions(-) diff --git a/.gitignore b/.gitignore index 7ffbc5752..cfdb519e7 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,3 @@ coverage/ node_modules/ npm-debug.log -.DS_Store diff --git a/Readme.md b/Readme.md index f2b12c323..373d5d889 100644 --- a/Readme.md +++ b/Readme.md @@ -392,7 +392,6 @@ 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`) -* `gracefulExit`: Determines whether to end gracefully. If `true`, every `pool.getConnection` or `pool.query` called before `pool.end` will success. If `false`, only commands / queries already in progress will complete, others will throw an error. ## Pool events @@ -452,25 +451,37 @@ trying to gracefully shutdown a server. To end all the connections in the pool, use the `end` method on the pool: ```js -pool.end(function (err) { +pool.end(false, function (err) { // all connections in the pool have ended }); ``` -The `end` method takes an _optional_ callback that you can use to know once -all the connections have ended. +The `end` method takes two _optional_ arguemnts: + +* `gracefulExit`: Determines whether to end gracefully. If `true`, every +`pool.getConnection` or `pool.query` called before `pool.end` will complete. +If `false`, only commands / queries already in progress will complete, +others will fail. (Default: `false`) + +* `callback`: Will be called once all the connections have ended. **Once `pool.end()` has been called, `pool.getConnection` and other operations can no longer be performed** -If `gracefulExit` is set to `true`, the connections end _gracefully_, so all - -pending queries will still complete and the time to end the pool will vary. +### Under the hood + +If `gracefulExit` is set to `true`, after calling `pool.end` the poll will +enter into the `pendingClose` state, all former or queued queries will still +complete. But the pool will no longer accept new queries. -The default `gracefulExit` is `false`, the following behavior will take effect. +This works by not queueing the `QUIT` packet on all the connections until there +is no connection in the aquiring state and no queued queries. All established +connections will still queue queries which were added before calling `pool.end`. -This works by calling `connection.end()` on every active connection in the -pool, which queues a `QUIT` packet on the connection. And sets a flag to -prevent `pool.getConnection` from continuing to create any new connections. +If `gracefulExit` is set to `false`, `pool.end` works by calling `connection.end()` +on every active connection in the pool, which queues a `QUIT` packet on the +connection. And sets a flag to prevent `pool.getConnection` from continuing to +create any new connections. Since this queues a `QUIT` packet on each connection, all commands / queries already in progress will complete, just like calling `connection.end()`. If diff --git a/lib/Pool.js b/lib/Pool.js index e7a3875eb..afada94a5 100644 --- a/lib/Pool.js +++ b/lib/Pool.js @@ -17,10 +17,10 @@ function Pool(options) { this._freeConnections = []; this._connectionQueue = []; this._closed = false; - this._pendingClosing = false; + this._pendingClose = false; } -Pool.prototype.getConnection = function (cb, queued) { +Pool.prototype.getConnection = function (cb, _queued) { if (this._closed) { var err = new Error('Pool is closed.'); @@ -34,13 +34,13 @@ Pool.prototype.getConnection = function (cb, queued) { var connection; var pool = this; - if (this._freeConnections.length > 0 && (!this._pendingClosing || queued)) { + if (this._freeConnections.length > 0 && (!this._pendingClose || _queued)) { connection = this._freeConnections.shift(); this.acquireConnection(connection, cb); return; } - if (this._pendingClosing) { + if (this._pendingClose) { var err = new Error('Pool is closed.'); err.code = 'POOL_CLOSED'; process.nextTick(function () { @@ -152,8 +152,8 @@ Pool.prototype.releaseConnection = function releaseConnection(connection) { this.emit('release', connection); } - if (this._pendingClosing) { - this.end(this._endCallback); + if (this._pendingClose) { + this.end(true, this._endCallback); } } @@ -172,7 +172,11 @@ Pool.prototype.releaseConnection = function releaseConnection(connection) { } }; -Pool.prototype.end = function (cb) { +Pool.prototype.end = function (gracefulExit, cb) { + if (typeof gracefulExit === 'function') { + cb = gracefulExit; + gracefulExit = false; + } if (typeof cb !== 'function') { cb = function (err) { if (err) throw err; @@ -194,7 +198,7 @@ Pool.prototype.end = function (cb) { readyToEnd = true; } - if (!this.config.gracefulExit || readyToEnd) { + if (!gracefulExit || readyToEnd) { this._closed = true; while (this._allConnections.length !== 0) { diff --git a/lib/PoolConfig.js b/lib/PoolConfig.js index b25c6dd9c..8c5017a27 100644 --- a/lib/PoolConfig.js +++ b/lib/PoolConfig.js @@ -20,9 +20,6 @@ function PoolConfig(options) { this.queueLimit = (options.queueLimit === undefined) ? 0 : Number(options.queueLimit); - this.gracefulExit = (options.gracefulExit === undefined) - ? false - : Boolean(options.gracefulExit); } PoolConfig.prototype.newConnectionConfig = function newConnectionConfig() { diff --git a/test/unit/pool/test-graceful-exit-ping.js b/test/unit/pool/test-graceful-exit-ping.js index 1d7d8e794..76d599c3a 100644 --- a/test/unit/pool/test-graceful-exit-ping.js +++ b/test/unit/pool/test-graceful-exit-ping.js @@ -4,8 +4,7 @@ var pool = common.createPool({ connectionLimit : 1, port : common.fakeServerPort, queueLimit : 5, - waitForConnections : true, - gracefulExit : true + waitForConnections : true }); var server = common.createFakeServer(); @@ -22,7 +21,7 @@ server.listen(common.fakeServerPort, function (err) { conn.release(); }); - pool.end(function (err) { + pool.end(true, function (err) { assert.ifError(err); server.destroy(); }); diff --git a/test/unit/pool/test-graceful-exit-queued.js b/test/unit/pool/test-graceful-exit-queued.js index 43927e195..99c3df12a 100644 --- a/test/unit/pool/test-graceful-exit-queued.js +++ b/test/unit/pool/test-graceful-exit-queued.js @@ -4,8 +4,7 @@ var pool = common.createPool({ connectionLimit : 1, port : common.fakeServerPort, queueLimit : 5, - waitForConnections : true, - gracefulExit : true + waitForConnections : true }); var server = common.createFakeServer(); @@ -16,7 +15,7 @@ server.listen(common.fakeServerPort, function (err) { pool.getConnection(function (err, conn) { assert.ifError(err); - pool.end(function (err) { + pool.end(true, function (err) { assert.ifError(err); server.destroy(); }); From 19705dad5133edb6f697558c526405f54fc12def Mon Sep 17 00:00:00 2001 From: HQidea Date: Sat, 9 Sep 2017 16:14:21 +0800 Subject: [PATCH 3/5] fix: refactor _pendingClosing to _pendingClose --- lib/Pool.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Pool.js b/lib/Pool.js index afada94a5..c2d4fbe15 100644 --- a/lib/Pool.js +++ b/lib/Pool.js @@ -212,7 +212,7 @@ Pool.prototype.end = function (gracefulExit, cb) { return; } - this._pendingClosing = true; + this._pendingClose = true; this._endCallback = cb; }; From 03ca7c210933e4a8fb3bead117a4507b045cc2af Mon Sep 17 00:00:00 2001 From: HQidea Date: Sun, 24 Sep 2017 17:41:04 +0800 Subject: [PATCH 4/5] chore: pool.end takes options --- Readme.md | 14 +++++--- lib/Pool.js | 24 ++++++++----- test/unit/pool/test-graceful-exit-ping.js | 4 ++- test/unit/pool/test-graceful-exit-query.js | 38 +++++++++++++++++++++ test/unit/pool/test-graceful-exit-queued.js | 4 ++- 5 files changed, 68 insertions(+), 16 deletions(-) create mode 100644 test/unit/pool/test-graceful-exit-query.js diff --git a/Readme.md b/Readme.md index 373d5d889..7fa669b98 100644 --- a/Readme.md +++ b/Readme.md @@ -451,14 +451,18 @@ trying to gracefully shutdown a server. To end all the connections in the pool, use the `end` method on the pool: ```js -pool.end(false, function (err) { +pool.end({ + gracefulExit: true +}, function (err) { // all connections in the pool have ended }); ``` -The `end` method takes two _optional_ arguemnts: +The `end` method takes two _optional_ arguments: -* `gracefulExit`: Determines whether to end gracefully. If `true`, every +* `options`: + + * `gracefulExit`: Determines whether to end gracefully. If `true`, every `pool.getConnection` or `pool.query` called before `pool.end` will complete. If `false`, only commands / queries already in progress will complete, others will fail. (Default: `false`) @@ -470,7 +474,7 @@ can no longer be performed** ### Under the hood -If `gracefulExit` is set to `true`, after calling `pool.end` the poll will +If `options.gracefulExit` is set to `true`, after calling `pool.end` the poll will enter into the `pendingClose` state, all former or queued queries will still complete. But the pool will no longer accept new queries. @@ -478,7 +482,7 @@ This works by not queueing the `QUIT` packet on all the connections until there is no connection in the aquiring state and no queued queries. All established connections will still queue queries which were added before calling `pool.end`. -If `gracefulExit` is set to `false`, `pool.end` works by calling `connection.end()` +If `options.gracefulExit` is set to `false`, `pool.end` works by calling `connection.end()` on every active connection in the pool, which queues a `QUIT` packet on the connection. And sets a flag to prevent `pool.getConnection` from continuing to create any new connections. diff --git a/lib/Pool.js b/lib/Pool.js index c2d4fbe15..24781c654 100644 --- a/lib/Pool.js +++ b/lib/Pool.js @@ -18,6 +18,9 @@ function Pool(options) { this._connectionQueue = []; this._closed = false; this._pendingClose = false; + this._endCallback = function (err) { + if (err) throw err; + }; } Pool.prototype.getConnection = function (cb, _queued) { @@ -153,7 +156,9 @@ Pool.prototype.releaseConnection = function releaseConnection(connection) { } if (this._pendingClose) { - this.end(true, this._endCallback); + this.end({ + gracefulExit: true + }); } } @@ -172,17 +177,18 @@ Pool.prototype.releaseConnection = function releaseConnection(connection) { } }; -Pool.prototype.end = function (gracefulExit, cb) { - if (typeof gracefulExit === 'function') { - cb = gracefulExit; - gracefulExit = false; +Pool.prototype.end = function (options, cb) { + if (!cb && typeof options === 'function') { + cb = options; + options = {}; } + if (typeof cb !== 'function') { - cb = function (err) { - if (err) throw err; - }; + cb = this._endCallback; } + options = options || {}; + var readyToEnd = false; var calledBack = false; var waitingClose = 0; @@ -198,7 +204,7 @@ Pool.prototype.end = function (gracefulExit, cb) { readyToEnd = true; } - if (!gracefulExit || readyToEnd) { + if (!options.gracefulExit || readyToEnd) { this._closed = true; while (this._allConnections.length !== 0) { diff --git a/test/unit/pool/test-graceful-exit-ping.js b/test/unit/pool/test-graceful-exit-ping.js index 76d599c3a..5cfae044d 100644 --- a/test/unit/pool/test-graceful-exit-ping.js +++ b/test/unit/pool/test-graceful-exit-ping.js @@ -21,7 +21,9 @@ server.listen(common.fakeServerPort, function (err) { conn.release(); }); - pool.end(true, function (err) { + pool.end({ + gracefulExit: true + }, function (err) { assert.ifError(err); server.destroy(); }); diff --git a/test/unit/pool/test-graceful-exit-query.js b/test/unit/pool/test-graceful-exit-query.js new file mode 100644 index 000000000..32f93c731 --- /dev/null +++ b/test/unit/pool/test-graceful-exit-query.js @@ -0,0 +1,38 @@ +var common = require('../../common'); +var assert = require('assert'); +var pool = common.createPool({ + connectionLimit : 2, + port : common.fakeServerPort, + queueLimit : 5, + waitForConnections : true +}); + +var server = common.createFakeServer(); + +server.listen(common.fakeServerPort, function (err) { + assert.ifError(err); + + pool.getConnection(function (err, conn) { + assert.ifError(err); + + pool.getConnection(function (err, conn2) { + assert.ifError(err); + + pool.query('SELECT 1', function (err, rows) { + assert.ifError(err); + assert.equal(rows.length, 1); + assert.equal(rows[0]['1'], 1); + }); + + pool.end({ + gracefulExit: true + }, function (err) { + assert.ifError(err); + server.destroy(); + }); + + conn.release(); + conn2.release(); + }); + }); +}); diff --git a/test/unit/pool/test-graceful-exit-queued.js b/test/unit/pool/test-graceful-exit-queued.js index 99c3df12a..96553bafe 100644 --- a/test/unit/pool/test-graceful-exit-queued.js +++ b/test/unit/pool/test-graceful-exit-queued.js @@ -15,7 +15,9 @@ server.listen(common.fakeServerPort, function (err) { pool.getConnection(function (err, conn) { assert.ifError(err); - pool.end(true, function (err) { + pool.end({ + gracefulExit: true + }, function (err) { assert.ifError(err); server.destroy(); }); From b8ace423940561c8d3fafec34d1820792b7fc842 Mon Sep 17 00:00:00 2001 From: HQidea Date: Fri, 28 Jun 2019 17:52:06 +0800 Subject: [PATCH 5/5] feat: add an option to PoolCluster.end --- lib/PoolCluster.js | 9 ++++-- test/unit/pool-cluster/test-end-graceful.js | 33 +++++++++++++++++++++ test/unit/pool-cluster/test-end-query.js | 31 +++++++++++++++++++ 3 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 test/unit/pool-cluster/test-end-graceful.js create mode 100644 test/unit/pool-cluster/test-end-query.js diff --git a/lib/PoolCluster.js b/lib/PoolCluster.js index d0aed2c75..39c739700 100644 --- a/lib/PoolCluster.js +++ b/lib/PoolCluster.js @@ -58,7 +58,12 @@ PoolCluster.prototype.add = function add(id, config) { this._clearFindCaches(); }; -PoolCluster.prototype.end = function end(callback) { +PoolCluster.prototype.end = function end(options, callback) { + if (!callback && typeof options === 'function') { + callback = options; + options = {}; + } + var cb = callback !== undefined ? callback : _cb; @@ -90,7 +95,7 @@ PoolCluster.prototype.end = function end(callback) { var node = this._nodes[nodeId]; waitingClose++; - node.pool.end(onEnd); + node.pool.end(options, onEnd); } if (waitingClose === 0) { diff --git a/test/unit/pool-cluster/test-end-graceful.js b/test/unit/pool-cluster/test-end-graceful.js new file mode 100644 index 000000000..6ee2b6ca2 --- /dev/null +++ b/test/unit/pool-cluster/test-end-graceful.js @@ -0,0 +1,33 @@ +var assert = require('assert'); +var common = require('../../common'); +var cluster = common.createPoolCluster(); +var server = common.createFakeServer(); + +var poolConfig = common.getTestConfig({port: common.fakeServerPort}); +cluster.add('SLAVE1', poolConfig); +cluster.add('SLAVE2', poolConfig); + +server.listen(common.fakeServerPort, function(err) { + assert.ifError(err); + + var pool = cluster.of('SLAVE*', 'ORDER'); + + pool.query('SELECT 1', function (err, rows) { + assert.ifError(err); + assert.equal(rows.length, 1); + assert.equal(rows[0]['1'], 1); + + pool.query('SELECT 2', function (err, rows) { + assert.ifError(err); + assert.equal(rows.length, 1); + assert.equal(rows[0]['2'], 2); + }); + + cluster.end({ + gracefulExit: true + }, function (err) { + assert.ifError(err); + server.destroy(); + }); + }); +}); diff --git a/test/unit/pool-cluster/test-end-query.js b/test/unit/pool-cluster/test-end-query.js new file mode 100644 index 000000000..1c999ef6b --- /dev/null +++ b/test/unit/pool-cluster/test-end-query.js @@ -0,0 +1,31 @@ +var assert = require('assert'); +var common = require('../../common'); +var cluster = common.createPoolCluster(); +var server = common.createFakeServer(); + +var poolConfig = common.getTestConfig({port: common.fakeServerPort}); +cluster.add('SLAVE1', poolConfig); +cluster.add('SLAVE2', poolConfig); + +server.listen(common.fakeServerPort, function(err) { + assert.ifError(err); + + var pool = cluster.of('SLAVE*', 'ORDER'); + + pool.query('SELECT 1', function (err, rows) { + assert.ifError(err); + assert.equal(rows.length, 1); + assert.equal(rows[0]['1'], 1); + + pool.query('SELECT 2', function (err) { + assert.ok(err); + assert.equal(err.message, 'Pool is closed.'); + assert.equal(err.code, 'POOL_CLOSED'); + }); + + cluster.end(function (err) { + assert.ifError(err); + server.destroy(); + }); + }); +});