Node-postgres: Connection terminated unexpectedly does not propagate to the active query

Created on 29 Jul 2018  路  4Comments  路  Source: brianc/node-postgres

Referring to this code:

https://github.com/brianc/node-postgres/blob/master/lib/client.js#L179-L188

First of all, it is not clear how to replicate this error.

Under what circumstances will the end event be triggered without calling .end() on the client?

I have tried:

const connection = await pool.connect();

await connection.query('SELECT pg_sleep(10)');

end then literally terminating the Internet connection, but that results in ETIMEDOUT rather than "Connection terminated unexpectedly".

Point is, this is happening in production application.

I read the notes at https://node-postgres.com/api/pool:

When a client is sitting idly in the pool it can still emit errors because it is connected to a live backend. If the backend goes down or a network partition is encountered all the idle, connected clients in your application will emit an error through the pool's error event emitter. The error listener is passed the error as the first argument and the client upon which the error occurred as the 2nd argument. The client will be automatically terminated and removed from the pool, it is only passed to the error handler in case you want to inspect it.

It is important you add an event listener to the pool to catch 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 exit.

Having read this, it is still unclear to me whats the reason this error cannot be propagated to the active query?

Perhaps I am overlooking something, but was the intention to structure the code as:

if (this.activeQuery) {
      // ..
- }
- if (!this._ending) {
+ } else if (!this._ending) {

?

This fixes the issue ("Connection terminated" propagates to the query), though I am uncertain what are the side effects.

question

Most helpful comment

Always use a pool, always add an error event listener to the pool. Not emitting the event when there鈥檚 an active query doesn鈥檛 let you not do this, because it could easily happen when there isn鈥檛 an active query.

That makes sense. It would also make sense then to throw an error if client attempts to create a query without error event listener defined.

All 4 comments

Having read this, it is still unclear to me whats the reason this error cannot be propagated to the active query?

It is, because it causes the query to fail. It鈥檚 just also emitted on the client, because it鈥檚 a client-level error (requires you to connect a new client if not using a pool, for example).

First of all, it is not clear how to replicate this error.

Under what circumstances will the end event be triggered without calling .end() on the client?

Connections being terminated by PostgreSQL, e.g. when shutting down or causing a client鈥檚 backend process to exit:

'use strict';

const pg = require('pg');

(async () => {
  const pool = new pg.Pool({
    host: '/var/run/postgresql',
  });

  const client = await pool.connect();

  pool.on('error', error => {
    console.error('error event on pool (%s)', error);
  });

  client.on('end', () => {
    console.log('end event on client');
    pool.end();
  });

  await pool.query('SELECT pg_terminate_backend($1)', [client.processID]);
})();

process.on('unhandledRejection', error => {
  throw error;
});

It is, because it causes the query to fail. It鈥檚 just also emitted on the client, because it鈥檚 a client-level error (requires you to connect a new client if not using a pool, for example).

Problem is that unless client defines "error" event handler, then the Node process is being terminated prior to the query error handler doing clean up.

Always use a pool, always add an error event listener to the pool. Not emitting the event when there鈥檚 an active query doesn鈥檛 let you not do this, because it could easily happen when there isn鈥檛 an active query.

Always use a pool, always add an error event listener to the pool. Not emitting the event when there鈥檚 an active query doesn鈥檛 let you not do this, because it could easily happen when there isn鈥檛 an active query.

That makes sense. It would also make sense then to throw an error if client attempts to create a query without error event listener defined.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

AhmedBHameed picture AhmedBHameed  路  3Comments

Phara0h picture Phara0h  路  4Comments

ClueLessEggHead picture ClueLessEggHead  路  3Comments

ossdev07 picture ossdev07  路  3Comments

v1co1n picture v1co1n  路  4Comments