diff --git a/src/connection/Connection.ts b/src/connection/Connection.ts index dfbb5e0790..99906d87bd 100644 --- a/src/connection/Connection.ts +++ b/src/connection/Connection.ts @@ -396,11 +396,17 @@ export class Connection { const usedQueryRunner = queryRunner || this.createQueryRunner("master"); try { - return await usedQueryRunner.query(query, parameters); // await is needed here because we are using finally + const result = await usedQueryRunner.query(query, parameters); - } finally { if (!queryRunner) await usedQueryRunner.release(); + + return result; + } catch (err) { + if (!queryRunner) + await usedQueryRunner.release(err); + + throw err; } } diff --git a/src/driver/postgres/PostgresQueryRunner.ts b/src/driver/postgres/PostgresQueryRunner.ts index ce7daeb8fa..310c191a24 100644 --- a/src/driver/postgres/PostgresQueryRunner.ts +++ b/src/driver/postgres/PostgresQueryRunner.ts @@ -101,11 +101,23 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner /** * Releases used database connection. * You cannot use query runner methods once its released. + * + * If `error` is truthy the released connection may be removed from the pool + * depending on the driver. */ - release(): Promise { + release(error?: any): Promise { this.isReleased = true; - if (this.releaseCallback) - this.releaseCallback(); + + if (this.releaseCallback) { + // severe errors may indicate an unrecoverable client, e.g. a client + // whose connection no longer exists (due to network issues, etc). + // the safest thing to do is instruct the pool to remove it, or it + // will stick around in the pool indefinitely, breaking every + // subsequent query that runs on it + const removeFromPool = Boolean(error && error.severity === "FATAL"); + + this.releaseCallback(removeFromPool); + } const index = this.driver.connectedQueryRunners.indexOf(this); if (index !== -1) this.driver.connectedQueryRunners.splice(index); diff --git a/src/query-runner/QueryRunner.ts b/src/query-runner/QueryRunner.ts index 62c9f78424..5fd91b2601 100644 --- a/src/query-runner/QueryRunner.ts +++ b/src/query-runner/QueryRunner.ts @@ -70,8 +70,11 @@ export interface QueryRunner { /** * Releases used database connection. * You cannot use query runner methods after connection is released. + * + * If `error` is truthy the released connection may be removed from the pool + * depending on the driver. */ - release(): Promise; + release(error?: any): Promise; /** * Removes all tables from the currently connected database.