-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Do not return broken or closed clients to the pool #2081
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
ccc25f4
Drop support for EOL versions of node (#2062)
brianc 5b01eb0
Remove password from stringified outputs (#2066)
brianc 8494cb4
Make `native` non-enumerable (#2065)
brianc e3a35e9
Use class-extends to wrap Pool (#1541)
NatalieWolfe 8c606ff
Continue support for creating a pg.Pool from another instance’s optio…
charmander 7aee261
Use user name as default database when user is non-default (#1679)
charmander b9f67a0
Prevent requeuing a broken client
johanneswuerbach 48ed190
Write tests for change
brianc 98dd655
Use node 13.6 in travis
brianc File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,3 +7,4 @@ package-lock.json | |
*.swp | ||
dist | ||
.DS_Store | ||
.vscode/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,7 @@ env: | |
node_js: | ||
- lts/dubnium | ||
- lts/erbium | ||
- 13 | ||
- 13.6 | ||
|
||
addons: | ||
postgresql: "10" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,6 +25,10 @@ class PendingItem { | |
} | ||
} | ||
|
||
function throwOnDoubleRelease () { | ||
throw new Error('Release called on client which has already been released to the pool.') | ||
} | ||
|
||
function promisify (Promise, callback) { | ||
if (callback) { | ||
return { callback: callback, result: undefined } | ||
|
@@ -60,6 +64,18 @@ class Pool extends EventEmitter { | |
constructor (options, Client) { | ||
super() | ||
this.options = Object.assign({}, options) | ||
|
||
if (options != null && 'password' in options) { | ||
// "hiding" the password so it doesn't show up in stack traces | ||
// or if the client is console.logged | ||
Object.defineProperty(this.options, 'password', { | ||
configurable: true, | ||
enumerable: false, | ||
writable: true, | ||
value: options.password | ||
}) | ||
} | ||
|
||
this.options.max = this.options.max || this.options.poolSize || 10 | ||
this.log = this.options.log || function () { } | ||
this.Client = this.options.Client || Client || require('pg').Client | ||
|
@@ -244,7 +260,7 @@ class Pool extends EventEmitter { | |
|
||
client.release = (err) => { | ||
if (released) { | ||
throw new Error('Release called on client which has already been released to the pool.') | ||
throwOnDoubleRelease() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. " |
||
} | ||
|
||
released = true | ||
|
@@ -280,7 +296,8 @@ class Pool extends EventEmitter { | |
_release (client, idleListener, err) { | ||
client.on('error', idleListener) | ||
|
||
if (err || this.ending) { | ||
// TODO(bmc): expose a proper, public interface _queryable and _ending | ||
if (err || this.ending || !client._queryable || client._ending) { | ||
this._remove(client) | ||
this._pulseQueue() | ||
return | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,6 +34,6 @@ | |
"pg-cursor": "^1.3.0" | ||
}, | ||
"peerDependencies": { | ||
"pg": ">5.0" | ||
"pg": ">=8.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
const Pool = require('../') | ||
|
||
const expect = require('expect.js') | ||
const net = require('net') | ||
|
||
describe('releasing clients', () => { | ||
it('removes a client which cannot be queried', async () => { | ||
// make a pool w/ only 1 client | ||
const pool = new Pool({ max: 1 }) | ||
expect(pool.totalCount).to.eql(0) | ||
const client = await pool.connect() | ||
expect(pool.totalCount).to.eql(1) | ||
expect(pool.idleCount).to.eql(0) | ||
// reach into the client and sever its connection | ||
client.connection.end() | ||
|
||
// wait for the client to error out | ||
const err = await new Promise((resolve) => client.once('error', resolve)) | ||
expect(err).to.be.ok() | ||
expect(pool.totalCount).to.eql(1) | ||
expect(pool.idleCount).to.eql(0) | ||
|
||
// try to return it to the pool - this removes it because its broken | ||
client.release() | ||
expect(pool.totalCount).to.eql(0) | ||
expect(pool.idleCount).to.eql(0) | ||
|
||
// make sure pool still works | ||
const { rows } = await pool.query('SELECT NOW()') | ||
expect(rows).to.have.length(1) | ||
await pool.end() | ||
}) | ||
|
||
it('removes a client which is ending', async () => { | ||
// make a pool w/ only 1 client | ||
const pool = new Pool({ max: 1 }) | ||
expect(pool.totalCount).to.eql(0) | ||
const client = await pool.connect() | ||
expect(pool.totalCount).to.eql(1) | ||
expect(pool.idleCount).to.eql(0) | ||
// end the client gracefully (but you shouldn't do this with pooled clients) | ||
client.end() | ||
|
||
// try to return it to the bool | ||
brianc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
client.release() | ||
expect(pool.totalCount).to.eql(0) | ||
expect(pool.idleCount).to.eql(0) | ||
|
||
// make sure pool still works | ||
const { rows } = await pool.query('SELECT NOW()') | ||
expect(rows).to.have.length(1) | ||
await pool.end() | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -51,6 +51,6 @@ | |
], | ||
"license": "MIT", | ||
"engines": { | ||
"node": ">= 4.5.0" | ||
"node": ">= 8.0.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
|
||
"use strict" | ||
const helper = require('./../test-helper') | ||
const assert = require('assert') | ||
|
||
const suite = new helper.Suite() | ||
|
||
suite.testAsync('BoundPool can be subclassed', async () => { | ||
const Pool = helper.pg.Pool; | ||
class SubPool extends Pool { | ||
|
||
} | ||
const subPool = new SubPool() | ||
const client = await subPool.connect() | ||
client.release() | ||
await subPool.end() | ||
assert(subPool instanceof helper.pg.Pool) | ||
}) | ||
|
||
suite.test('calling pg.Pool without new throws', () => { | ||
const Pool = helper.pg.Pool; | ||
assert.throws(() => { | ||
const pool = Pool() | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
|
||
"use strict" | ||
const helper = require('./../test-helper') | ||
const assert = require('assert') | ||
|
||
const suite = new helper.Suite() | ||
|
||
suite.test('Native should not be enumerable', () => { | ||
const keys = Object.keys(helper.pg) | ||
assert.strictEqual(keys.indexOf('native'), -1) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
|
||
"use strict" | ||
const helper = require('./../test-helper') | ||
const assert = require('assert') | ||
const util = require('util') | ||
|
||
const suite = new helper.Suite() | ||
|
||
const password = 'FAIL THIS TEST' | ||
|
||
suite.test('Password should not exist in toString() output', () => { | ||
const pool = new helper.pg.Pool({ password }) | ||
const client = new helper.pg.Client({ password }) | ||
assert(pool.toString().indexOf(password) === -1); | ||
assert(client.toString().indexOf(password) === -1); | ||
}) | ||
|
||
suite.test('Password should not exist in util.inspect output', () => { | ||
const pool = new helper.pg.Pool({ password }) | ||
const client = new helper.pg.Client({ password }) | ||
const depth = 20; | ||
assert(util.inspect(pool, { depth }).indexOf(password) === -1); | ||
assert(util.inspect(client, { depth }).indexOf(password) === -1); | ||
}) | ||
|
||
suite.test('Password should not exist in json.stringfy output', () => { | ||
const pool = new helper.pg.Pool({ password }) | ||
const client = new helper.pg.Client({ password }) | ||
const depth = 20; | ||
assert(JSON.stringify(pool).indexOf(password) === -1); | ||
assert(JSON.stringify(client).indexOf(password) === -1); | ||
}) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What’s this for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the test to iterate a stream multiple times w/ async iterator stopped working in node 13.7....I've had occasional breaks before on single semver minor versions of non LTS node...if this doesn't resolve itself w/ 13.8 I'll have to track it down & see if it was something they intentionally changed w/ async iterators on streams.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
btw...found the issue:
nodejs/node#31508