Skip to content

Commit

Permalink
fix: prevent reuse of broken connections in postgres pool (#7792)
Browse files Browse the repository at this point in the history
this updates the error handler we have on the postgres connection
object to release back with an error in the case of an error so
the underlying `pg-pool` knows to remove the connection from the
rotation
  • Loading branch information
imnotjames committed Jun 28, 2021
1 parent 2adfe36 commit 5cf368a
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 16 deletions.
Expand Up @@ -41,11 +41,6 @@ export class AuroraDataApiPostgresQueryRunner extends PostgresQueryRunnerWrapper
*/
protected databaseConnectionPromise: Promise<any>;

/**
* Special callback provided by a driver used to release a created connection.
*/
protected releaseCallback: Function;

// -------------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------------
Expand Down
33 changes: 22 additions & 11 deletions src/driver/postgres/PostgresQueryRunner.ts
Expand Up @@ -50,7 +50,7 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner
/**
* Special callback provided by a driver used to release a created connection.
*/
protected releaseCallback: Function;
protected releaseCallback?: (err: any) => void;

// -------------------------------------------------------------------------
// Constructor
Expand Down Expand Up @@ -84,7 +84,7 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner
this.driver.connectedQueryRunners.push(this);
this.databaseConnection = connection;

const onErrorCallback = () => this.release();
const onErrorCallback = (err: Error) => this.releasePostgresConnection(err);
this.releaseCallback = () => {
this.databaseConnection.removeListener("error", onErrorCallback);
release();
Expand All @@ -99,7 +99,7 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner
this.driver.connectedQueryRunners.push(this);
this.databaseConnection = connection;

const onErrorCallback = () => this.release();
const onErrorCallback = (err: Error) => this.releasePostgresConnection(err);
this.releaseCallback = () => {
this.databaseConnection.removeListener("error", onErrorCallback);
release();
Expand All @@ -114,22 +114,33 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner
}

/**
* Releases used database connection.
* You cannot use query runner methods once its released.
* Release a connection back to the pool, optionally specifying an Error to release with.
* Per pg-pool documentation this will prevent the pool from re-using the broken connection.
*/
release(): Promise<void> {
private async releasePostgresConnection(err?: Error) {
if (this.isReleased) {
return Promise.resolve();
return
}

this.isReleased = true;
if (this.releaseCallback)
this.releaseCallback();
if (this.releaseCallback) {
this.releaseCallback(err);
this.releaseCallback = undefined
}

const index = this.driver.connectedQueryRunners.indexOf(this);
if (index !== -1) this.driver.connectedQueryRunners.splice(index, 1);

return Promise.resolve();
if (index !== -1) {
this.driver.connectedQueryRunners.splice(index, 1);
}
}

/**
* Releases used database connection.
* You cannot use query runner methods once its released.
*/
release(): Promise<void> {
return this.releasePostgresConnection();
}

/**
Expand Down

0 comments on commit 5cf368a

Please sign in to comment.