From 98bbffbfd11123364dfb7f6d894395f658823586 Mon Sep 17 00:00:00 2001 From: Raphael Medaer Date: Thu, 18 Mar 2021 14:17:44 +0100 Subject: [PATCH 1/3] Implement a `PoolError` with dedicated codes Previously the Pool was throwing built-in JS `Error`. It's therefore difficult to identify each kind of error. This patch allow the developer to identify each type of error raised by the Pool with a `PoolError`. Each `PoolError` has its own code and a message (original message for backward compatibility). Codes and errors are documented in README file. --- packages/pg-pool/README.md | 14 ++++++++++++++ packages/pg-pool/index.js | 23 +++++++++++++++++------ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/packages/pg-pool/README.md b/packages/pg-pool/README.md index c6d7e9287..26016093e 100644 --- a/packages/pg-pool/README.md +++ b/packages/pg-pool/README.md @@ -331,6 +331,20 @@ var bluebirdPool = new Pool({ __please note:__ in node `<=0.12.x` the pool will throw if you do not provide a promise constructor in one of the two ways mentioned above. In node `>=4.0.0` the pool will use the native promise implementation by default; however, the two methods above still allow you to "bring your own." +## error management + +Errors throwed by the pool are instances of `PoolError`. Each `PoolError` has a message (short description of the exception) and a structured code composed of 5 characters string starting with letter `Z`. +The following table list the existing `PoolError`s and their code: + +| Code | Message | +| ----- | ------------------------------------------------------------------------ | +| Z0001 | Cannot use a pool after calling end on the pool | +| Z0002 | Passing a function as the first parameter to pool.query is not supported | +| Z0003 | Release called on client which has already been released to the pool | +| Z0004 | Called end on pool more than once | +| Z0005 | Timeout exceeded when trying to connect | +| Z0009 | Unexpected condition | + ## maxUses and read-replica autoscaling (e.g. AWS Aurora) The maxUses config option can help an application instance rebalance load against a replica set that has been auto-scaled after the connection pool is already full of healthy connections. diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 780f18652..2ce9dc9a2 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -24,7 +24,7 @@ class PendingItem { } function throwOnDoubleRelease() { - throw new Error('Release called on client which has already been released to the pool.') + throw new PoolError('Release called on client which has already been released to the pool.', 'Z0003') } function promisify(Promise, callback) { @@ -58,6 +58,15 @@ function makeIdleListener(pool, client) { } } +class PoolError extends Error { + // A PoolError is an error throwed during a Pool process. Each type of error contains a specific "code". + // Please document in README file the error codes. + constructor(message, code) { + super(message) + this.code = code + } +} + class Pool extends EventEmitter { constructor(options, Client) { super() @@ -143,7 +152,7 @@ class Pool extends EventEmitter { if (!this._isFull()) { return this.newClient(pendingItem) } - throw new Error('unexpected condition') + throw new PoolError('unexpected condition', 'Z0009') } _remove(client) { @@ -160,7 +169,7 @@ class Pool extends EventEmitter { connect(cb) { if (this.ending) { - const err = new Error('Cannot use a pool after calling end on the pool') + const err = new PoolError('Cannot use a pool after calling end on the pool', 'Z0001') return cb ? cb(err) : this.Promise.reject(err) } @@ -192,7 +201,7 @@ class Pool extends EventEmitter { // we're going to call it with a timeout error removeWhere(this._pendingQueue, (i) => i.callback === queueCallback) pendingItem.timedOut = true - response.callback(new Error('timeout exceeded when trying to connect')) + response.callback(new PoolError('timeout exceeded when trying to connect', 'Z0005')) }, this.options.connectionTimeoutMillis) this._pendingQueue.push(pendingItem) @@ -334,7 +343,7 @@ class Pool extends EventEmitter { if (typeof text === 'function') { const response = promisify(this.Promise, text) setImmediate(function () { - return response.callback(new Error('Passing a function as the first parameter to pool.query is not supported')) + return response.callback(new PoolError('Passing a function as the first parameter to pool.query is not supported', 'Z0002')) }) return response.result } @@ -385,7 +394,7 @@ class Pool extends EventEmitter { end(cb) { this.log('ending') if (this.ending) { - const err = new Error('Called end on pool more than once') + const err = new PoolError('Called end on pool more than once', 'Z0004') return cb ? cb(err) : this.Promise.reject(err) } this.ending = true @@ -408,3 +417,5 @@ class Pool extends EventEmitter { } } module.exports = Pool +module.exports.Pool = Pool +module.exports.PoolError = PoolError From 8af68859a3872b0934d6ae141b77caf10d9c570e Mon Sep 17 00:00:00 2001 From: Raphael Medaer Date: Thu, 18 Mar 2021 15:53:56 +0100 Subject: [PATCH 2/3] Fix linting --- packages/pg-pool/index.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 2ce9dc9a2..4968b0098 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -59,12 +59,12 @@ function makeIdleListener(pool, client) { } class PoolError extends Error { - // A PoolError is an error throwed during a Pool process. Each type of error contains a specific "code". - // Please document in README file the error codes. - constructor(message, code) { - super(message) - this.code = code - } + // A PoolError is an error throwed during a Pool process. Each type of error contains a specific "code". + // Please document in README file the error codes. + constructor(message, code) { + super(message) + this.code = code + } } class Pool extends EventEmitter { @@ -343,7 +343,9 @@ class Pool extends EventEmitter { if (typeof text === 'function') { const response = promisify(this.Promise, text) setImmediate(function () { - return response.callback(new PoolError('Passing a function as the first parameter to pool.query is not supported', 'Z0002')) + return response.callback( + new PoolError('Passing a function as the first parameter to pool.query is not supported', 'Z0002') + ) }) return response.result } From 72dfbe7ad522a17b15f43ce17dd23eb8ece261dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Medaer?= Date: Mon, 5 Jul 2021 09:14:10 +0200 Subject: [PATCH 3/3] Fix english grammar Co-authored-by: Charmander <~@charmander.me> --- packages/pg-pool/index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 4968b0098..725d7ef14 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -59,8 +59,7 @@ function makeIdleListener(pool, client) { } class PoolError extends Error { - // A PoolError is an error throwed during a Pool process. Each type of error contains a specific "code". - // Please document in README file the error codes. + // A PoolError is an error thrown during a Pool operation. Each type of error contains a specific "code", documented in pg-pool’s README. constructor(message, code) { super(message) this.code = code