Skip to content

Commit 60d6313

Browse files
committed
Merge remote-tracking branch 'origin/master' into bmc/search-path
2 parents dbdad87 + 4b4d97b commit 60d6313

File tree

17 files changed

+164
-96
lines changed

17 files changed

+164
-96
lines changed

.github/workflows/ci.yml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: CI
22

3-
on: [push]
3+
on: [push, pull_request]
44

55
jobs:
66
build:
@@ -17,12 +17,13 @@ jobs:
1717
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
1818
strategy:
1919
matrix:
20-
node: ['8', '10', '12', '14', '16', '17']
21-
name: Node ${{ matrix.node }}
20+
node: ['8', '10', '12', '14', '16', '18']
21+
os: [ubuntu-latest, windows-latest, macos-latest]
22+
name: Node.js ${{ matrix.node }} (${{ matrix.os }})
2223
steps:
23-
- uses: actions/checkout@v2
24+
- uses: actions/checkout@v3
2425
- name: Setup node
25-
uses: actions/setup-node@v2
26+
uses: actions/setup-node@v3
2627
with:
2728
node-version: ${{ matrix.node }}
2829
cache: yarn

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ For richer information consult the commit log on github with referenced pull req
44

55
We do not include break-fix version release in this file.
66

7+
### pg-pool@3.5.0
8+
9+
- Add connection [lifetime limit](https://github.com/brianc/node-postgres/pull/2698) config option.
10+
711
### pg@8.7.0
812

913
- Add optional config to [pool](https://github.com/brianc/node-postgres/pull/2568) to allow process to exit if pool is idle.

SPONSORS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ node-postgres is made possible by the helpful contributors from the community as
1111
- [Dataform](https://dataform.co/)
1212
- [Eaze](https://www.eaze.com/)
1313
- [simpleanalytics](https://simpleanalytics.com/)
14-
- [n8n.io]https://n8n.io/
14+
- [n8n.io](https://n8n.io/)
1515

1616
# Supporters
1717

packages/pg-cursor/index.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ class Cursor extends EventEmitter {
8686
}
8787

8888
_closePortal() {
89+
if (this.state === 'done') return
90+
8991
// because we opened a named portal to stream results
9092
// we need to close the same named portal. Leaving a named portal
9193
// open can lock tables for modification if inside a transaction.
@@ -97,6 +99,8 @@ class Cursor extends EventEmitter {
9799
if (this.state !== 'error') {
98100
this.connection.sync()
99101
}
102+
103+
this.state = 'done'
100104
}
101105

102106
handleRowDescription(msg) {
@@ -213,7 +217,6 @@ class Cursor extends EventEmitter {
213217
}
214218

215219
this._closePortal()
216-
this.state = 'done'
217220
this.connection.once('readyForQuery', function () {
218221
cb()
219222
})

packages/pg-cursor/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "pg-cursor",
3-
"version": "2.7.1",
3+
"version": "2.7.3",
44
"description": "Query cursor extension for node-postgres",
55
"main": "index.js",
66
"directories": {
@@ -18,7 +18,7 @@
1818
"license": "MIT",
1919
"devDependencies": {
2020
"mocha": "^7.1.2",
21-
"pg": "^8.7.1"
21+
"pg": "^8.7.3"
2222
},
2323
"peerDependencies": {
2424
"pg": "^8"

packages/pg-pool/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ because its so common to just run a query and return the client to the pool afte
136136
var pool = new Pool()
137137
var time = await pool.query('SELECT NOW()')
138138
var name = await pool.query('select $1::text as name', ['brianc'])
139-
console.log(name.rows[0].name, 'says hello at', time.rows[0].name)
139+
console.log(name.rows[0].name, 'says hello at', time.rows[0].now)
140140
```
141141

142142
you can also use a callback here if you'd like:

packages/pg-pool/index.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ class Pool extends EventEmitter {
8484
this.options.max = this.options.max || this.options.poolSize || 10
8585
this.options.maxUses = this.options.maxUses || Infinity
8686
this.options.allowExitOnIdle = this.options.allowExitOnIdle || false
87+
this.options.maxLifetimeSeconds = this.options.maxLifetimeSeconds || 0
8788
this.log = this.options.log || function () {}
8889
this.Client = this.options.Client || Client || require('pg').Client
8990
this.Promise = this.options.Promise || global.Promise
@@ -94,6 +95,7 @@ class Pool extends EventEmitter {
9495

9596
this._clients = []
9697
this._idle = []
98+
this._expired = new WeakSet()
9799
this._pendingQueue = []
98100
this._endCallback = undefined
99101
this.ending = false
@@ -123,6 +125,7 @@ class Pool extends EventEmitter {
123125
}
124126
return
125127
}
128+
126129
// if we don't have any waiting, do nothing
127130
if (!this._pendingQueue.length) {
128131
this.log('no queued requests')
@@ -248,6 +251,22 @@ class Pool extends EventEmitter {
248251
} else {
249252
this.log('new client connected')
250253

254+
if (this.options.maxLifetimeSeconds !== 0) {
255+
setTimeout(() => {
256+
this.log('ending client due to expired lifetime')
257+
this._expired.add(client)
258+
const idleIndex = this._idle.findIndex((idleItem) => idleItem.client === client)
259+
if (idleIndex !== -1) {
260+
this._acquireClient(
261+
client,
262+
new PendingItem((err, client, clientRelease) => clientRelease()),
263+
idleListener,
264+
false
265+
)
266+
}
267+
}, this.options.maxLifetimeSeconds * 1000)
268+
}
269+
251270
return this._acquireClient(client, pendingItem, idleListener, true)
252271
}
253272
})
@@ -318,6 +337,15 @@ class Pool extends EventEmitter {
318337
return
319338
}
320339

340+
const isExpired = this._expired.has(client)
341+
if (isExpired) {
342+
this.log('remove expired client')
343+
this._expired.delete(client)
344+
this._remove(client)
345+
this._pulseQueue()
346+
return
347+
}
348+
321349
// idle timeout
322350
let tid
323351
if (this.options.idleTimeoutMillis) {
@@ -414,6 +442,10 @@ class Pool extends EventEmitter {
414442
return this._idle.length
415443
}
416444

445+
get expiredCount() {
446+
return this._clients.reduce((acc, client) => acc + (this._expired.has(client) ? 1 : 0), 0)
447+
}
448+
417449
get totalCount() {
418450
return this._clients.length
419451
}

packages/pg-pool/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "pg-pool",
3-
"version": "3.4.1",
3+
"version": "3.5.1",
44
"description": "Connection pool for node-postgres",
55
"main": "index.js",
66
"directories": {
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
'use strict'
2+
const co = require('co')
3+
const expect = require('expect.js')
4+
5+
const describe = require('mocha').describe
6+
const it = require('mocha').it
7+
const path = require('path')
8+
9+
const Pool = require('../')
10+
11+
describe('lifetime timeout', () => {
12+
it('connection lifetime should expire and remove the client', (done) => {
13+
const pool = new Pool({ maxLifetimeSeconds: 1 })
14+
pool.query('SELECT NOW()')
15+
pool.on('remove', () => {
16+
console.log('expired while idle - on-remove event')
17+
expect(pool.expiredCount).to.equal(0)
18+
expect(pool.totalCount).to.equal(0)
19+
done()
20+
})
21+
})
22+
it('connection lifetime should expire and remove the client after the client is done working', (done) => {
23+
const pool = new Pool({ maxLifetimeSeconds: 1 })
24+
pool.query('SELECT pg_sleep(1.01)')
25+
pool.on('remove', () => {
26+
console.log('expired while busy - on-remove event')
27+
expect(pool.expiredCount).to.equal(0)
28+
expect(pool.totalCount).to.equal(0)
29+
done()
30+
})
31+
})
32+
it(
33+
'can remove expired clients and recreate them',
34+
co.wrap(function* () {
35+
const pool = new Pool({ maxLifetimeSeconds: 1 })
36+
let query = pool.query('SELECT pg_sleep(1)')
37+
expect(pool.expiredCount).to.equal(0)
38+
expect(pool.totalCount).to.equal(1)
39+
yield query
40+
expect(pool.expiredCount).to.equal(0)
41+
expect(pool.totalCount).to.equal(0)
42+
yield pool.query('SELECT NOW()')
43+
expect(pool.expiredCount).to.equal(0)
44+
expect(pool.totalCount).to.equal(1)
45+
})
46+
)
47+
})

packages/pg-query-stream/package.json

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "pg-query-stream",
3-
"version": "4.2.1",
3+
"version": "4.2.3",
44
"description": "Postgres query result returned as readable stream",
55
"main": "./dist/index.js",
66
"types": "./dist/index.d.ts",
@@ -37,13 +37,12 @@
3737
"concat-stream": "~1.0.1",
3838
"eslint-plugin-promise": "^3.5.0",
3939
"mocha": "^7.1.2",
40-
"pg": "^8.7.1",
40+
"pg": "^8.7.3",
4141
"stream-spec": "~0.3.5",
42-
"stream-tester": "0.0.5",
4342
"ts-node": "^8.5.4",
4443
"typescript": "^4.0.3"
4544
},
4645
"dependencies": {
47-
"pg-cursor": "^2.7.1"
46+
"pg-cursor": "^2.7.3"
4847
}
4948
}

0 commit comments

Comments
 (0)