У меня есть таблица postgresql, заполненная тысячами данных временных рядов каждый день. У меня есть приложение, позволяющее пользователю получать эти данные. Запросы могут занимать от 200 мс до 30 сек c в зависимости от временного диапазона, поэтому их необходимо отменять, чтобы избежать бесполезной нагрузки на производство.
Поскольку существуют миллиарды данных, использование потока для их извлечения неизбежно.
Так что мне удалось получить рабочую конечную точку с потоком данных, как это показано в документах pg-обещания, и сделать ее отменяемой, закрыв курсор в пределах pg-query-stream
.
Здесь пример того, что делается в этой конечной точке (dataStream () вызывается после построения запроса):
const pgp = require("pg-promise")();
const QueryStream = require("pg-query-stream");
const db = pgp({
host: "1.2.3.4",
port: 5432,
database: "db",
user: "user",
password: "password",
max: 2,
});
// query is an SQL string
dataStream(query, req, res, next) {
const qs = new QueryStream(query);
// "close" event is triggered on client request cancelation
req.on("close", () => {
qs.destroy();
});
return db.stream(qs, s => {
formatDataAndStreamToRes(s, req, res);
s.on("error", error => handleError(error));
})
.catch(error => handleError(error, query));
}
Прекрасно работает для нескольких вызовов, но в какой-то момент (выполнение от 8 до 10 вызовов) чтобы быстро проверить возможность отмены), приложение создает sh с этим стеком:
\node_modules\pg-promise\node_modules\pg\lib\client.js:346
if (self.activeQuery.name) {
^
TypeError: Cannot read property 'name' of null
at Connection.<anonymous> (\node_modules\pg-promise\node_modules\pg\lib\client.js:346:26)
at Connection.emit (events.js:311:20)
at Socket.<anonymous> (\node_modules\pg-promise\node_modules\pg\lib\connection.js:120:12)
at Socket.emit (events.js:311:20)
at addChunk (_stream_readable.js:294:12)
at readableAddChunk (_stream_readable.js:275:11)
at Socket.Readable.push (_stream_readable.js:209:10)
at TCP.onStreamRead (internal/stream_base_commons.js:186:23)
Так что я подозреваю, что вызов qs.destroy () для закрытия потока не является правильным способом сделать это, даже если хотя курсор на стороне сервера хорошо разрушен.
Спасибо разработчикам node- postgres и pg-обещания за вашу работу.