@constructive-io/graphql-server 5.16.10 → 5.16.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/esm/server.js CHANGED
@@ -225,24 +225,39 @@ class Server {
225
225
  }
226
226
  this.listenClient = client;
227
227
  this.listenRelease = release;
228
+ // Attached before any query is issued: an 'error' event on a Client with no
229
+ // listener is rethrown by Node and takes the whole process down.
230
+ client.on('error', (e) => {
231
+ this.dropListener(client, 'Error with database notify listener', e);
232
+ });
228
233
  client.on('notification', ({ channel, payload }) => {
229
234
  if (channel === 'schema:update' && payload) {
230
235
  log.info('schema:update', payload);
231
236
  this.flush(payload);
232
237
  }
233
238
  });
234
- client.query('LISTEN "schema:update"');
235
- client.on('error', (e) => {
236
- if (this.shuttingDown) {
237
- release();
238
- return;
239
- }
240
- this.error('Error with database notify listener', e);
241
- release();
242
- this.addEventListener();
239
+ client.query('LISTEN "schema:update"').catch((e) => {
240
+ this.dropListener(client, 'Failed to LISTEN for schema:update', e);
243
241
  });
244
242
  this.log('connected and listening for changes...');
245
243
  }
244
+ dropListener(client, message, err) {
245
+ // Another path (shutdown, an earlier failure) already tore this client down.
246
+ if (this.listenClient !== client)
247
+ return;
248
+ const release = this.listenRelease;
249
+ this.listenClient = null;
250
+ this.listenRelease = null;
251
+ client.removeAllListeners('notification');
252
+ client.removeAllListeners('error');
253
+ if (this.shuttingDown) {
254
+ release?.();
255
+ return;
256
+ }
257
+ this.error(message, err);
258
+ release?.();
259
+ this.addEventListener();
260
+ }
246
261
  async removeEventListener() {
247
262
  if (!this.listenClient || !this.listenRelease) {
248
263
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constructive-io/graphql-server",
3
- "version": "5.16.10",
3
+ "version": "5.16.11",
4
4
  "author": "Constructive <developers@constructive.io>",
5
5
  "description": "Constructive GraphQL Server",
6
6
  "main": "index.js",
@@ -96,5 +96,5 @@
96
96
  "supertest": "^7.2.2",
97
97
  "ts-node": "^10.9.2"
98
98
  },
99
- "gitHead": "d0d796b7eb0d16c8c19405a49c0ca62ce3df117b"
99
+ "gitHead": "4839d3c123304735a7aa74fb4e45af41cf947567"
100
100
  }
package/server.d.ts CHANGED
@@ -39,6 +39,7 @@ declare class Server {
39
39
  getPool(): Pool;
40
40
  addEventListener(): void;
41
41
  listenForChanges(err: Error | null, client: PoolClient, release: () => void): void;
42
+ private dropListener;
42
43
  removeEventListener(): Promise<void>;
43
44
  close(opts?: {
44
45
  closeCaches?: boolean;
package/server.js CHANGED
@@ -232,24 +232,39 @@ class Server {
232
232
  }
233
233
  this.listenClient = client;
234
234
  this.listenRelease = release;
235
+ // Attached before any query is issued: an 'error' event on a Client with no
236
+ // listener is rethrown by Node and takes the whole process down.
237
+ client.on('error', (e) => {
238
+ this.dropListener(client, 'Error with database notify listener', e);
239
+ });
235
240
  client.on('notification', ({ channel, payload }) => {
236
241
  if (channel === 'schema:update' && payload) {
237
242
  log.info('schema:update', payload);
238
243
  this.flush(payload);
239
244
  }
240
245
  });
241
- client.query('LISTEN "schema:update"');
242
- client.on('error', (e) => {
243
- if (this.shuttingDown) {
244
- release();
245
- return;
246
- }
247
- this.error('Error with database notify listener', e);
248
- release();
249
- this.addEventListener();
246
+ client.query('LISTEN "schema:update"').catch((e) => {
247
+ this.dropListener(client, 'Failed to LISTEN for schema:update', e);
250
248
  });
251
249
  this.log('connected and listening for changes...');
252
250
  }
251
+ dropListener(client, message, err) {
252
+ // Another path (shutdown, an earlier failure) already tore this client down.
253
+ if (this.listenClient !== client)
254
+ return;
255
+ const release = this.listenRelease;
256
+ this.listenClient = null;
257
+ this.listenRelease = null;
258
+ client.removeAllListeners('notification');
259
+ client.removeAllListeners('error');
260
+ if (this.shuttingDown) {
261
+ release?.();
262
+ return;
263
+ }
264
+ this.error(message, err);
265
+ release?.();
266
+ this.addEventListener();
267
+ }
253
268
  async removeEventListener() {
254
269
  if (!this.listenClient || !this.listenRelease) {
255
270
  return;