- You probably want to add an event listener to the pool to catch background errors!
- Just like other event emitters, if a pool emits an error event and no listeners are added node will emit an
- uncaught error and potentially crash your node process.
+ The pool has a default no-op error listener so an idle client error does not become an uncaught exception. Add your
+ own listener to observe, log, or otherwise handle these background errors.
### release
diff --git a/packages/pg-pool/README.md b/packages/pg-pool/README.md
index 80c644788..7d9538d0c 100644
--- a/packages/pg-pool/README.md
+++ b/packages/pg-pool/README.md
@@ -234,11 +234,14 @@ const pool = new Pool()
// attach an error handler to the pool for when a connected, idle client
// receives an error by being disconnected, etc
pool.on('error', function (error, client) {
- // handle this in the same way you would treat process.on('uncaughtException')
+ // observe or otherwise handle the background error
// it is supplied the error as well as the idle client which received the error
})
```
+Pools include a default no-op error listener so an idle client error does not become an uncaught exception. Add your own
+listener to observe, log, or otherwise handle these background errors.
+
#### connect
Fired whenever the pool creates a **new** `pg.Client` instance and successfully connects it to the backend.
diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js
index ab514fa88..7977c3a33 100644
--- a/packages/pg-pool/index.js
+++ b/packages/pg-pool/index.js
@@ -66,6 +66,7 @@ function makeIdleListener(pool, client) {
class Pool extends EventEmitter {
constructor(options, Client) {
super()
+ this.on('error', () => {})
this.options = Object.assign({}, options)
if (options != null && 'password' in options) {
diff --git a/packages/pg-pool/test/events.js b/packages/pg-pool/test/events.js
index 809c2159a..73c53b619 100644
--- a/packages/pg-pool/test/events.js
+++ b/packages/pg-pool/test/events.js
@@ -7,6 +7,26 @@ const it = require('mocha').it
const Pool = require('../')
describe('events', function () {
+ it('does not throw an unhandled error event', function () {
+ const pool = new Pool({ Client: mockClient() })
+ const expectedError = new Error('unexpected idle client error')
+
+ expect(() => pool.emit('error', expectedError)).to.not.throwException()
+ })
+
+ it('emits errors to user listeners', function () {
+ const pool = new Pool({ Client: mockClient() })
+ const expectedError = new Error('unexpected idle client error')
+ let emittedError
+
+ pool.on('error', function (error) {
+ emittedError = error
+ })
+ pool.emit('error', expectedError)
+
+ expect(emittedError).to.be(expectedError)
+ })
+
it('emits connect before callback', function (done) {
const pool = new Pool()
let emittedClient = false
diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js
index 2b13c1de7..df4207fc8 100644
--- a/packages/pg/lib/client.js
+++ b/packages/pg/lib/client.js
@@ -50,6 +50,7 @@ function coerceNumberOrDefault(value, defaultValue) {
class Client extends EventEmitter {
constructor(config) {
super()
+ this.on('error', () => {})
this.connectionParameters = new ConnectionParameters(config)
this.user = this.connectionParameters.user
diff --git a/packages/pg/lib/native/client.js b/packages/pg/lib/native/client.js
index 9ec3c8c03..3775edf42 100644
--- a/packages/pg/lib/native/client.js
+++ b/packages/pg/lib/native/client.js
@@ -22,6 +22,7 @@ const queryQueueLengthDeprecationNotice = nodeUtils.deprecate(
const Client = (module.exports = function (config) {
EventEmitter.call(this)
+ this.on('error', () => {})
config = config || {}
this._Promise = config.Promise || global.Promise
diff --git a/packages/pg/test/native/evented-api-tests.js b/packages/pg/test/native/evented-api-tests.js
index 220fcaece..2e150e440 100644
--- a/packages/pg/test/native/evented-api-tests.js
+++ b/packages/pg/test/native/evented-api-tests.js
@@ -6,6 +6,26 @@ const assert = require('assert')
const suite = new helper.Suite()
const test = suite.test.bind(suite)
+test('does not throw an unhandled error event', function () {
+ const client = new Client(helper.config)
+ const expectedError = new Error('unexpected idle client error')
+
+ assert.doesNotThrow(() => client.emit('error', expectedError))
+})
+
+test('emits errors to user listeners', function () {
+ const client = new Client(helper.config)
+ const expectedError = new Error('unexpected idle client error')
+ let emittedError
+
+ client.on('error', (error) => {
+ emittedError = error
+ })
+ client.emit('error', expectedError)
+
+ assert.strictEqual(emittedError, expectedError)
+})
+
const setupClient = function () {
const client = new Client(helper.config)
client.connect()
diff --git a/packages/pg/test/unit/client/configuration-tests.js b/packages/pg/test/unit/client/configuration-tests.js
index 63d4ea649..d6549bc56 100644
--- a/packages/pg/test/unit/client/configuration-tests.js
+++ b/packages/pg/test/unit/client/configuration-tests.js
@@ -10,6 +10,26 @@ const pgdatabase = process.env['PGDATABASE'] || process.env.USER
const pgport = process.env['PGPORT'] || 5432
test('client settings', function () {
+ test('does not throw an unhandled error event', function () {
+ const client = new Client()
+ const expectedError = new Error('unexpected idle client error')
+
+ assert.doesNotThrow(() => client.emit('error', expectedError))
+ })
+
+ test('emits errors to user listeners', function () {
+ const client = new Client()
+ const expectedError = new Error('unexpected idle client error')
+ let emittedError
+
+ client.on('error', (error) => {
+ emittedError = error
+ })
+ client.emit('error', expectedError)
+
+ assert.strictEqual(emittedError, expectedError)
+ })
+
test('defaults', function () {
const client = new Client()
assert.equal(client.user, pguser)