Make a test case and fix for errors drainging the pool (#49)

* this bug leaves the pool empty even if there is work
   to be done, if there are enough consecutive errors to
   empty the pool

re brianc/node-pg-pool#48
This commit is contained in:
Russ Tyndall 2017-04-13 09:26:53 -04:00 committed by Brian C
parent 5918a9e105
commit c89b74bb5d
2 changed files with 58 additions and 0 deletions

View File

@ -3,6 +3,26 @@ var util = require('util')
var EventEmitter = require('events').EventEmitter
var objectAssign = require('object-assign')
// there is a bug in the generic pool where it will not recreate
// destroyed workers (even if there is waiting work to do) unless
// there is a min specified. Make sure we keep some connections
// SEE: https://github.com/coopernurse/node-pool/pull/186
// SEE: https://github.com/brianc/node-pg-pool/issues/48
// SEE: https://github.com/strongloop/loopback-connector-postgresql/issues/231
function _ensureMinimum () {
var i, diff, waiting
if (this._draining) return
waiting = this._waitingClients.size()
if (this._factory.min > 0) { // we have positive specified minimum
diff = this._factory.min - this._count
} else if (waiting > 0) { // we have no minimum, but we do have work to do
diff = Math.min(waiting, this._factory.max - this._count)
}
for (i = 0; i < diff; i++) {
this._createResource()
}
};
var Pool = module.exports = function (options, Client) {
if (!(this instanceof Pool)) {
return new Pool(options, Client)
@ -17,6 +37,14 @@ var Pool = module.exports = function (options, Client) {
this.options.create = this.options.create || this._create.bind(this)
this.options.destroy = this.options.destroy || this._destroy.bind(this)
this.pool = new genericPool.Pool(this.options)
// Monkey patch to ensure we always finish our work
// - There is a bug where callbacks go uncalled if min is not set
// - We might still not want a connection to *always* exist
// - but we do want to create up to max connections if we have work
// - still waiting
// This should be safe till the version of pg-pool is upgraded
// SEE: https://github.com/coopernurse/node-pool/pull/186
this.pool._ensureMinimum = _ensureMinimum
this.onCreate = this.options.onCreate
}

View File

@ -194,6 +194,36 @@ describe('pool', function () {
})
})
describe('pool error handling', function () {
it('Should complete these queries without dying', function (done) {
var pgPool = new Pool()
var pool = pgPool.pool
pool._factory.max = 1
pool._factory.min = null
var errors = 0
var shouldGet = 0
function runErrorQuery () {
shouldGet++
return new Promise(function (resolve, reject) {
pgPool.query("SELECT 'asd'+1 ").then(function (res) {
reject(res) // this should always error
}).catch(function (err) {
errors++
resolve(err)
})
})
}
var ps = []
for (var i = 0; i < 5; i++) {
ps.push(runErrorQuery())
}
Promise.all(ps).then(function () {
expect(shouldGet).to.eql(errors)
done()
})
})
})
process.on('unhandledRejection', function (e) {
console.error(e.message, e.stack)
setImmediate(function () {