From 7b88ee9c54aa4fd3b5f2ef6e885f603f7e6d5ef1 Mon Sep 17 00:00:00 2001 From: Ben Page Date: Tue, 28 Oct 2014 18:40:47 -0500 Subject: [PATCH] properly uses latest the version of generic pool validate connections releasing connections that close for any reason remove unnecessary events --- .gitignore | 1 + README.md | 38 ++++++++----- lib/connection-pool.js | 107 ++++++++++++----------------------- lib/pooled-connection.js | 26 +++++---- package.json | 47 ++++++++++++--- test/connection-pool.test.js | 42 ++++++-------- 6 files changed, 131 insertions(+), 130 deletions(-) diff --git a/.gitignore b/.gitignore index 2f83b4a..4743e9d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ npm-debug.log node_modules/ *.sublime-* +.idea/ diff --git a/README.md b/README.md index 4bf3539..056c1a4 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,40 @@ # tedious-connection-pool A simple connection pool for [tedious](http://github.com/pekim/tedious). - Status: Experimental - ## Example -The only difference from the regular tedious API is how the connection is obtained. -Once a Connection object has been acquired, the tedious API can be used with the -connection as normal. +The only difference from the regular tedious API is how the connection is obtained and released. Once a Connection object has been acquired, the tedious API can be used with the connection as normal. ```javascript var ConnectionPool = require('tedious-connection-pool'); var pool = new ConnectionPool(poolConfig, connectionConfig); -pool.requestConnection(function (err, connection) { +pool.acquire(function (err, connection) { if(!err) { var request = new Request('select 42', function(err, rowCount) { assert.strictEqual(rowCount, 1); // Release the connection back to the pool. - connection.close(); + connection.release(); }); request.on('row', function(columns) { assert.strictEqual(columns[0].value, 42); }); - connection.on('connect', function(err) { - connection.execSql(request); - }); + connection.execSql(request); } }); ``` -When the connection is closed it is returned to the pool. +When the connection is released it is returned to the pool. It is then available to be reused. ##Class: ConnectionPool ### new ConnectionPool(poolConfig, connectionConfig) -* `poolConfig` {Object} +* `poolConfig` {Object} the configuration for [generic-pool](https://github.com/coopernurse/node-pool) (see link for full list of arguments) * `max` {Number} The maximum number of connections there can be in the pool. Default = `10` * `min` {Number} The minimun of connections there can be in the pool. Default = `0` * `idleTimeoutMillis` {Number} The Number of milliseconds before closing an unused connection. Default = `30000` @@ -48,8 +42,26 @@ It is then available to be reused. * `connectionConfig` {Object} The same configuration that would be used to [create a tedious Connection](http://pekim.github.com/tedious/api-connection.html#function_newConnection). -### connectionPool.requestConnection(callback) +### connectionPool.acquire(callback) * `callback` {Function} Callback function * `error` {Error Object} * `connection` {Object} A [Connection](http://pekim.github.com/tedious/api-connection.html) + +### connectionPool.release(connection) + +* `connection` {Object} A [Connection](http://pekim.github.com/tedious/api-connection.html) + +### connectionPool.drain(callback) + +* `callback` {Function} Callback function + +##Class: PooledConnection +* An extension of the tedious [Connection](http://pekim.github.com/tedious/api-connection.html) object. + +### connectionPool.release() + +## Version 0.2.x Breaking Changes +* To acquire a connection, call on acquire() on a ConnectionPool rather than requestConnection(). +* After acquiring a PooledConnection, do not wait for the 'connected' event. The connection is received connected. +* Call release() on a PooledConnection to release the it back to the pool. close() permenantly closes the connection (as close() behaves in in tedious). \ No newline at end of file diff --git a/lib/connection-pool.js b/lib/connection-pool.js index 2c26503..2e645c0 100644 --- a/lib/connection-pool.js +++ b/lib/connection-pool.js @@ -1,86 +1,49 @@ -var PooledConnection = require('./pooled-connection'), - PoolModule = require('generic-pool'); - -var connectionEventNames = [ - 'connect', - 'end', - 'debug', - 'infoMessage', - 'errorMessage', - 'databaseChange', - 'languageChange', - 'charsetChange', - 'secure' -]; +'use strict'; +var poolModule = require('generic-pool'); +var PooledConnection = require('./pooled-connection'); function ConnectionPool(poolConfig, connectionConfig) { - var self = this, - param = { - name: poolConfig.name || "", - log: poolConfig.log, - create: function(callback) { - var connection = new PooledConnection(connectionConfig); - var connected = false; - - connection.on('connect', function(err) { - if (connected) { - // The real 'connect' event has already been emmited by the - // connection, and processed in this function. - // - // This is now the fake connect event emmited by the acquire function, - // for applications' benefit. - return; - } - - if (err) { - callback(err, null); - } else { - connected = true; + var self = this; - connection.on('release', function() { - connectionEventNames.forEach(function removeAllListeners(eventName) { - connection.removeAllListeners(eventName); - }); - - self.pool.release(connection); - }); - - callback(null, connection); - } - }); + this.pool = poolModule.Pool({ + name: poolConfig.name || "", + create: function (callback) { + var connection = new PooledConnection(self, connectionConfig); + connection.on('connect', function (err) { + if (err) + callback(err, null); + else + callback(null, connection); + }); }, - destroy: function(connection) { - connection._close(); + destroy: function (connection) { + if (!connection.isEnded) //con.close() calls pool.destroy(), which calls con.close() - isEnded stops looping + connection.close(); + }, + validate: function(connection) { + return !connection.closed && !connection.isEnded; }, max: poolConfig.max || 10, min: poolConfig.min || 0, - idleTimeoutMillis: poolConfig.idleTimeoutMillis || 30000 - }; - - this.pool = PoolModule.Pool(param); + idleTimeoutMillis: poolConfig.idleTimeoutMillis || 30000, + log: poolConfig.log + }); } -module.exports = ConnectionPool; - +ConnectionPool.prototype.acquire = function (callback) { + return this.pool.acquire(callback); +}; -ConnectionPool.prototype.requestConnection = function(callback) { - var self = this; - this.pool.acquire(function(err, connection) { - if(err) { - callback(err, null); - } - else { - callback(null, connection); - connection.emit('connect'); - } - }); +ConnectionPool.prototype.release = function (connection) { + return this.pool.release(connection); }; -ConnectionPool.prototype.drain = function(callback) { - var self = this; +ConnectionPool.prototype.drain = function (callback) { + var self = this; - self.pool.drain(function() { - self.pool.destroyAllNow(); - callback(); - }); + this.pool.drain(function () { + self.pool.destroyAllNow(callback); + }); }; + +module.exports = ConnectionPool; diff --git a/lib/pooled-connection.js b/lib/pooled-connection.js index 6d29ff9..37c84fd 100644 --- a/lib/pooled-connection.js +++ b/lib/pooled-connection.js @@ -1,19 +1,23 @@ var Connection = require('tedious').Connection; -var util = require('util'); -function PooledConnection(config) { - Connection.call(this, config); -} +function PooledConnection(connectionPool, config) { + var self = this; -util.inherits(PooledConnection, Connection); + this.connectionPool = connectionPool; + this.isEnded = false; -PooledConnection.prototype.close = function() { - this.emit('end'); - this.emit('release'); //used by the pool -}; + Connection.call(this, config); + + this.on('end', function () { + self.isEnded = true; + self.connectionPool.pool.destroy(self); + }); +} + +PooledConnection.prototype = Object.create(Connection.prototype); -PooledConnection.prototype._close = function() { - return Connection.prototype.close.call(this); +PooledConnection.prototype.release = function () { + this.pool.release(this); }; module.exports = PooledConnection; diff --git a/package.json b/package.json index de40f94..69889af 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "tedious-connection-pool", - "version": "0.1.1", + "version": "0.2.1", "description": "Connection Pool for tedious.", "main": "lib/connection-pool.js", "dependencies": { - "generic-pool": "2.0.4" + "generic-pool": "2.1.x" }, "scripts": { "test": "test" @@ -18,18 +18,49 @@ "connection", "pool" ], - "author": "Mike D Pilsbury", + "author": { + "name": "Mike D Pilsbury", + "email": "mike.pilsbury@gmail.com" + }, "contributors": [ { "name": "e11137", "email": "rogelio.canedo@gmail.com" + }, + { + "name": "Ben Page", + "email": "ben.page@openreign.com" + } + ], + "maintainers": [ + { + "name": "Mike D Pilsbury", + "email": "mike.pilsbury@gmail.com" + }, + { + "name": "Ben Page", + "email": "ben.page@openreign.com" + } + ], + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/brentertz/scapegoat/blob/master/LICENSE-MIT" } ], - "license": "MIT", "devDependencies": { - "tedious": "0.0.7", - "mocha": "1.6.0", - "async": "0.1.22" + "tedious": ">=0.0.7", + "mocha": ">=1.6.0", + "async": ">=0.1.22" + }, + "licenses": "MIT", + "readmeFilename": "README.md", + "gitHead": "22e4053020343706eb9c998e9354263cf2ced759", + "bugs": { + "url": "https://github.com/pekim/tedious-connection-pool/issues" }, - "licenses": "MIT" + "homepage": "https://github.com/pekim/tedious-connection-pool", + "_id": "tedious-connection-pool@0.1.3", + "_shasum": "1be288bfd2da593b2111ec02efed508f95f1772b", + "_from": "..\\tedious-connection-pool" } diff --git a/test/connection-pool.test.js b/test/connection-pool.test.js index b5ceaed..44424a3 100644 --- a/test/connection-pool.test.js +++ b/test/connection-pool.test.js @@ -6,7 +6,7 @@ var Request = require('tedious').Request; var connectionConfig = { userName: 'test', password: 'test', - server: '192.168.1.212', + server: 'dev1', // options: { // debug: { // packet: true, @@ -22,11 +22,11 @@ describe('ConnectionPool', function() { var poolConfig = {max: 1, log: false}; it('should connect, and end', function(done) { - testPool(poolConfig, poolConfig.max, requestConnectionAndClose, done); + testPool(poolConfig, poolConfig.max, acquireAndClose, done); }); it('should connect, select, and end', function(done) { - testPool(poolConfig, poolConfig.max, requestConnectionSelectAndClose, done); + testPool(poolConfig, poolConfig.max, acquireSelectAndClose, done); }); }); @@ -35,11 +35,11 @@ describe('ConnectionPool', function() { var numberOfConnectionsToUse = poolConfig.max; it('should connect, and end', function(done) { - testPool(poolConfig, numberOfConnectionsToUse, requestConnectionAndClose, done); + testPool(poolConfig, numberOfConnectionsToUse, acquireAndClose, done); }); it('should connect, select, and end', function(done) { - testPool(poolConfig, numberOfConnectionsToUse, requestConnectionSelectAndClose, done); + testPool(poolConfig, numberOfConnectionsToUse, acquireSelectAndClose, done); }); }); @@ -48,11 +48,11 @@ describe('ConnectionPool', function() { var numberOfConnectionsToUse = 20; it('should connect, and end', function(done) { - testPool(poolConfig, numberOfConnectionsToUse, requestConnectionAndClose, done); + testPool(poolConfig, numberOfConnectionsToUse, acquireAndClose, done); }); it('should connect, select, and end', function(done) { - testPool(poolConfig, numberOfConnectionsToUse, requestConnectionSelectAndClose, done); + testPool(poolConfig, numberOfConnectionsToUse, acquireSelectAndClose, done); }); }); }); @@ -78,39 +78,29 @@ function testPool(poolConfig, numberOfConnectionsToUse, useConnectionFunction, d }); } -function requestConnectionAndClose(pool, done) { - pool.requestConnection(function (err, connection) { +function acquireAndClose(pool, done) { + pool.acquire(function (err, connection) { assert.ok(!err); - connection.on('connect', function(err) { - connection.close(); - }); - - connection.on('end', function(err) { - done(); - }); + connection.release(); + done(); }); } -function requestConnectionSelectAndClose(pool, done) { - pool.requestConnection(function (err, connection) { +function acquireSelectAndClose(pool, done) { + pool.acquire(function (err, connection) { assert.ok(!err); var request = new Request('select 42', function(err, rowCount) { assert.strictEqual(rowCount, 1); - connection.close(); + connection.release(); + done(); }); request.on('row', function(columns) { assert.strictEqual(columns[0].value, 42); }); - connection.on('connect', function(err) { - connection.execSql(request); - }); - - connection.on('end', function(err) { - done(); - }); + connection.execSql(request); }); }