mirror of
https://github.com/brianc/node-postgres.git
synced 2025-12-08 20:16:25 +00:00
Add connection lifetime limit option and tests (#2698)
Co-authored-by: ChrisG0x20 <position0x45@hotmail.com>
This commit is contained in:
parent
5508c0ee6b
commit
8392918d7b
@ -84,6 +84,7 @@ class Pool extends EventEmitter {
|
||||
this.options.max = this.options.max || this.options.poolSize || 10
|
||||
this.options.maxUses = this.options.maxUses || Infinity
|
||||
this.options.allowExitOnIdle = this.options.allowExitOnIdle || false
|
||||
this.options.maxLifetimeSeconds = this.options.maxLifetimeSeconds || 0
|
||||
this.log = this.options.log || function () {}
|
||||
this.Client = this.options.Client || Client || require('pg').Client
|
||||
this.Promise = this.options.Promise || global.Promise
|
||||
@ -94,6 +95,7 @@ class Pool extends EventEmitter {
|
||||
|
||||
this._clients = []
|
||||
this._idle = []
|
||||
this._expired = new WeakSet()
|
||||
this._pendingQueue = []
|
||||
this._endCallback = undefined
|
||||
this.ending = false
|
||||
@ -123,6 +125,7 @@ class Pool extends EventEmitter {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// if we don't have any waiting, do nothing
|
||||
if (!this._pendingQueue.length) {
|
||||
this.log('no queued requests')
|
||||
@ -248,6 +251,17 @@ class Pool extends EventEmitter {
|
||||
} else {
|
||||
this.log('new client connected')
|
||||
|
||||
if (this.options.maxLifetimeSeconds !== 0) {
|
||||
setTimeout(() => {
|
||||
this.log('ending client due to expired lifetime')
|
||||
this._expired.add(client)
|
||||
const idleIndex = this._idle.findIndex(idleItem => idleItem.client === client)
|
||||
if (idleIndex !== -1) {
|
||||
this._acquireClient(client, new PendingItem((err, client, clientRelease) => clientRelease()), idleListener, false)
|
||||
}
|
||||
}, this.options.maxLifetimeSeconds * 1000)
|
||||
}
|
||||
|
||||
return this._acquireClient(client, pendingItem, idleListener, true)
|
||||
}
|
||||
})
|
||||
@ -318,6 +332,15 @@ class Pool extends EventEmitter {
|
||||
return
|
||||
}
|
||||
|
||||
const isExpired = this._expired.has(client)
|
||||
if (isExpired) {
|
||||
this.log('remove expired client')
|
||||
this._expired.delete(client)
|
||||
this._remove(client)
|
||||
this._pulseQueue()
|
||||
return
|
||||
}
|
||||
|
||||
// idle timeout
|
||||
let tid
|
||||
if (this.options.idleTimeoutMillis) {
|
||||
@ -414,6 +437,10 @@ class Pool extends EventEmitter {
|
||||
return this._idle.length
|
||||
}
|
||||
|
||||
get expiredCount() {
|
||||
return this._clients.reduce((acc, client) => acc + (this._expired.has(client) ? 1 : 0), 0)
|
||||
}
|
||||
|
||||
get totalCount() {
|
||||
return this._clients.length
|
||||
}
|
||||
|
||||
46
packages/pg-pool/test/lifetime-timeout.js
Normal file
46
packages/pg-pool/test/lifetime-timeout.js
Normal file
@ -0,0 +1,46 @@
|
||||
'use strict'
|
||||
const co = require('co')
|
||||
const expect = require('expect.js')
|
||||
|
||||
const describe = require('mocha').describe
|
||||
const it = require('mocha').it
|
||||
const path = require('path')
|
||||
|
||||
const Pool = require('../')
|
||||
|
||||
describe('lifetime timeout', () => {
|
||||
it('connection lifetime should expire and remove the client', (done) => {
|
||||
const pool = new Pool({ maxLifetimeSeconds: 1 })
|
||||
pool.query('SELECT NOW()')
|
||||
pool.on('remove', () => {
|
||||
console.log('expired while idle - on-remove event')
|
||||
expect(pool.expiredCount).to.equal(0)
|
||||
expect(pool.totalCount).to.equal(0)
|
||||
done()
|
||||
})
|
||||
})
|
||||
it('connection lifetime should expire and remove the client after the client is done working', (done) => {
|
||||
const pool = new Pool({ maxLifetimeSeconds: 1 })
|
||||
pool.query('SELECT pg_sleep(1.01)')
|
||||
pool.on('remove', () => {
|
||||
console.log('expired while busy - on-remove event')
|
||||
expect(pool.expiredCount).to.equal(0)
|
||||
expect(pool.totalCount).to.equal(0)
|
||||
done()
|
||||
})
|
||||
})
|
||||
it('can remove expired clients and recreate them',
|
||||
co.wrap(function* () {
|
||||
const pool = new Pool({ maxLifetimeSeconds: 1 })
|
||||
let query = pool.query('SELECT pg_sleep(1)')
|
||||
expect(pool.expiredCount).to.equal(0)
|
||||
expect(pool.totalCount).to.equal(1)
|
||||
yield query
|
||||
expect(pool.expiredCount).to.equal(0)
|
||||
expect(pool.totalCount).to.equal(0)
|
||||
yield pool.query('SELECT NOW()')
|
||||
expect(pool.expiredCount).to.equal(0)
|
||||
expect(pool.totalCount).to.equal(1)
|
||||
})
|
||||
)
|
||||
})
|
||||
Loading…
x
Reference in New Issue
Block a user