node-postgres icon indicating copy to clipboard operation
node-postgres copied to clipboard

Cannot work out why 'connect' and 'error' events do not fire on Pool

Open kpturner opened this issue 3 years ago • 4 comments

This is the code (Typescript)

import { Pool } from 'pg';

const pool = new Pool({ connectionString });  
// The connection string points to a non-existent database 'postgresql://:@127.0.0.1:49175/foo'
pool.on('connect', () => {
    console.log('Connected');
});
pool.on('error', (err) => {
    console.error(err);   <<<<<< This does not fire
});

try {
   pool.connect();
} catch (err) {
   console.error(err);   <<<<<< We don't even get here
}

What happens is that the node.js process just crashes.

kpturner avatar Jun 09 '22 10:06 kpturner

Mmm, they do fire if I await the connection

await pool.connect()

But once I get a connection, if I then bring down the postgresql service unceremoniously, again the whole process crashes out. None of the error events fire to enable me to catch it.

node_modules/pg-protocol/src/parser.ts:369
      name === 'notice' ? new NoticeMessage(length, messageValue) : new DatabaseError(messageValue, length, name)
                                                                    ^
error: terminating connection due to administrator command
    at Parser.parseErrorMessage (/Users/kpturner/fotech/panoptes-ui-prototype/node_modules/pg-protocol/src/parser.ts:369:69)
    at Parser.handlePacket (/Users/kpturner/fotech/panoptes-ui-prototype/node_modules/pg-protocol/src/parser.ts:188:21)
    at Parser.parse (/Users/kpturner/fotech/panoptes-ui-prototype/node_modules/pg-protocol/src/parser.ts:103:30)
    at Socket.<anonymous> (/Users/kpturner/fotech/panoptes-ui-prototype/node_modules/pg-protocol/src/index.ts:7:48)
    at Socket.emit (node:events:390:28)
    at Socket.emit (node:domain:475:12)
    at addChunk (node:internal/streams/readable:315:12)
    at readableAddChunk (node:internal/streams/readable:289:9)
    at Socket.Readable.push (node:internal/streams/readable:228:10)
    at TCP.onStreamRead (node:internal/stream_base_commons:199:23) {
  length: 116,
  severity: 'FATAL',
  code: '57P01',
  detail: undefined,
  hint: undefined,
  position: undefined,
  internalPosition: undefined,
  internalQuery: undefined,
  where: undefined,
  schema: undefined,
  table: undefined,
  column: undefined,
  dataType: undefined,
  constraint: undefined,
  file: 'postgres.c',
  line: '2925',
  routine: 'ProcessInterrupts'
}

kpturner avatar Jun 09 '22 13:06 kpturner

This helped https://github.com/brianc/node-postgres/issues/2499#issuecomment-805477725

So now I am puzzling over

Re-initializing the PostgreSQL notification client after connection loss failed: Stopping PostgreSQL reconnection attempts after 3000ms timeout has been reached.

kpturner avatar Jun 09 '22 14:06 kpturner

@kpturner you need to use pool as per documentation

import { Pool } from 'pg';

const pool = new Pool({ connectionString });  

pool.on('connect', () => {
    console.log('Connected');
});
pool.on('error', (err) => {
    console.error(err); 
});

+ pool.query('your query').then(console.log).catch(console.error);

- try {
-   pool.connect();
- } catch (err) {
-   console.error(err); 
- }

dyrkow avatar Jun 15 '22 10:06 dyrkow

@kpturner you need to use pool as per documentation

import { Pool } from 'pg';

const pool = new Pool({ connectionString });  

pool.on('connect', () => {
    console.log('Connected');
});
pool.on('error', (err) => {
    console.error(err); 
});

+ pool.query('your query').then(console.log).catch(console.error);

- try {
-   pool.connect();
- } catch (err) {
-   console.error(err); 
- }

I am not sure I follow that. I don't want to have to run a query to find out that the connected attempt failed. I want to connect to the pool in a server and then, at some point later, run queries etc. I need to be able to know if I am successfully connected before attempting to run queries. I also need to know if the database goes offline when I was previously connected.

The documentation seems very unclear on the whole subject. I have managed to achieve what I need to achieve (without running a query) by doing it like this (which as far as I can see is undocumented but described here https://github.com/brianc/node-postgres/issues/2499#issuecomment-805477725) :

import { Pool } from 'pg';

const pool = new Pool({ connectionString });  
// The connection string points to a non-existent database 'postgresql://:@127.0.0.1:49175/foo'
pool.on('connect', () => {
    console.log('Connected');
    pool.on('error', (err) => {
      console.error(err);   <<<<<< This DOES fire if the database goes offline
    });
});

try {
   const client = await pool.connect(); <<<<<<< The "await" is important
   const handler = (err: Error) => {
       Do stuff   
   };
   client.on('error', handler);  <<<< This fires if the database goes offline
} catch (err) {
   console.error(err);   <<<<<< This fires as long as we use "await"
}

kpturner avatar Jun 15 '22 12:06 kpturner