Skip to content

Commit b9f67a0

Browse files
johanneswuerbachbrianc
authored andcommitted
Prevent requeuing a broken client
If a client is not queryable, the pool should prevent requeuing instead of strictly enforcing errors to be propagated back to it.
1 parent 7aee261 commit b9f67a0

File tree

2 files changed

+59
-0
lines changed

2 files changed

+59
-0
lines changed

packages/pg-pool/index.js

+25
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,31 @@ class PendingItem {
2525
}
2626
}
2727

28+
function throwOnRelease () {
29+
throw new Error('Release called on client which has already been released to the pool.')
30+
}
31+
32+
function release (client, err) {
33+
client.release = throwOnRelease
34+
if (err || this.ending || !client._queryable || client._ending) {
35+
this._remove(client)
36+
this._pulseQueue()
37+
return
38+
}
39+
40+
// idle timeout
41+
let tid
42+
if (this.options.idleTimeoutMillis) {
43+
tid = setTimeout(() => {
44+
this.log('remove idle client')
45+
this._remove(client)
46+
}, this.options.idleTimeoutMillis)
47+
}
48+
49+
this._idle.push(new IdleItem(client, tid))
50+
this._pulseQueue()
51+
}
52+
2853
function promisify (Promise, callback) {
2954
if (callback) {
3055
return { callback: callback, result: undefined }

packages/pg-pool/test/error-handling.js

+34
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,40 @@ describe('pool error handling', function () {
181181
})
182182
})
183183

184+
describe('releasing a not queryable client', () => {
185+
it('removes the client from the pool', (done) => {
186+
const pool = new Pool({ max: 1 })
187+
const connectionError = new Error('connection failed')
188+
189+
pool.once('error', () => {
190+
// Ignore error on pool
191+
})
192+
193+
pool.connect((err, client) => {
194+
expect(err).to.be(undefined)
195+
196+
client.once('error', (err) => {
197+
expect(err).to.eql(connectionError)
198+
199+
// Releasing the client should remove it from the pool,
200+
// whether called with an error or not
201+
client.release()
202+
203+
// Verify that the pool is still usuable and new client has been
204+
// created
205+
pool.query('SELECT $1::text as name', ['brianc'], (err, res) => {
206+
expect(err).to.be(undefined)
207+
expect(res.rows).to.eql([{ name: 'brianc' }])
208+
209+
pool.end(done)
210+
})
211+
})
212+
213+
client.emit('error', connectionError)
214+
})
215+
})
216+
})
217+
184218
describe('pool with lots of errors', () => {
185219
it('continues to work and provide new clients', co.wrap(function* () {
186220
const pool = new Pool({ max: 1 })

0 commit comments

Comments
 (0)