NodeJS с сокетом.io и postgres ПРОСЛУШИВАЮТ

#javascript #node.js #websocket #socket.io #pg

#javascript #node.js #websocket #socket.io #страница

Вопрос:

Я пытаюсь заставить свой интерфейс отслеживать события всякий раз, когда изменяется определенная таблица в моей базе данных postgres.

События Postgres запускаются отлично, и я могу передавать их через соккер.подключение к io, но у меня проблемы с надежностью. Я получаю (node:26) UnhandledPromiseRejectionWarning: Error: Client was closed and is not queryable ошибки на своем сервере, и часто события не передаются и не перехватываются сокетом. Я предполагаю, что это связано с тем, как я подключаюсь к клиентам Socket / db.

конфигурация pg:

 const {Pool} = require('pg');
const production = process.env.NODE_ENV === 'production';

const connectionString = `postgresql://${process.env.DB_USER}:${process.env.DB_PASSWORD}@${process.env.DB_HOST}:${process.env.DB_PORT}/${process.env.DB_DATABASE}`

const pool = new Pool({
    connectionString: process.env.CONNECTION_STRING ? process.env.CONNECTION_STRING : connectionString,
  ssl: production,
  connectionTimeoutMillis : 5000,
  idleTimeoutMillis : 30000
});
  

index.js

 io.of("/marketDetails").on('connect', (socket) => {
  pool.connect((err, client, release) => {
    if (err) { 
      console.log(err);
      return;
    }
    
    client.query('LISTEN update_table');
    
    client.on('notification', async(data) => {
      console.log("notified of table change")
      handleDBEvent(socket, data);
    })

    socket.on("disconnect", () => {
      client.query('UNLISTEN update_table');

    })
    
    release();
  })
});
  

Я получаю уведомления об определенных изменениях в таблице, но очень непоследовательно.

Ответ №1:

Вы немедленно release подключаете клиент базы данных, который вы приобрели, до того, как могут появиться какие-либо уведомления, и вы получаете сообщение об ошибке каждый раз, когда сокет отключается, и вы пытаетесь запустить UNLISTEN команду на выпущенном клиенте, соединение с которым было закрыто через 30 секунд.

Вместо этого используйте

 socket.on("disconnect", async () => {
  try {
    await client.query('UNLISTEN update_table');
  } finally {
    release();
  }
});
  

Кстати, я бы рекомендовал не устанавливать новое подключение к базе данных для каждого сокета.клиент ввода-вывода, база данных слишком ценна для этого. Вместо этого создайте единый клиент для своего приложения (возможно, вам даже не понадобится пул), попросите его прослушивать update_table события (возможно, только при подключении сокетов), а затем транслировать каждое событие во все подключенные в данный момент сокеты.