#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
события (возможно, только при подключении сокетов), а затем транслировать каждое событие во все подключенные в данный момент сокеты.