diff --git a/packages/pg-query-stream/test/error.ts b/packages/pg-query-stream/test/error.ts index 8ddb4da7d..5f7a78565 100644 --- a/packages/pg-query-stream/test/error.ts +++ b/packages/pg-query-stream/test/error.ts @@ -170,4 +170,24 @@ describe('error recovery', () => { conn.release() await pool.end() }) + + it('does not crash when query_timeout fires without callback', async () => { + const client = new Client({ query_timeout: 50 }) + await client.connect() + + const stream = new QueryStream('SELECT pg_sleep(10)') + + // cursor.on('error') fires synchronously when handleError is called + // stream.on('error') fires asynchronously via destroy() + // Use cursor for immediate error detection + const errorPromise = new Promise((resolve) => { + stream.cursor.on('error', resolve) + }) + + client.query(stream) + + const error = await errorPromise + assert.equal(error.message, 'Query read timeout') + await client.end() + }) }) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index df430f881..2534f9ca7 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -592,7 +592,7 @@ class Client extends EventEmitter { } if (readTimeout) { - queryCallback = query.callback + queryCallback = query.callback || (() => {}) readTimeoutTimer = setTimeout(() => { const error = new Error('Query read timeout') diff --git a/packages/pg/lib/native/client.js b/packages/pg/lib/native/client.js index 4bee7ce3c..667bf613d 100644 --- a/packages/pg/lib/native/client.js +++ b/packages/pg/lib/native/client.js @@ -184,7 +184,7 @@ Client.prototype.query = function (config, values, callback) { } if (readTimeout) { - queryCallback = query.callback + queryCallback = query.callback || (() => {}) readTimeoutTimer = setTimeout(() => { const error = new Error('Query read timeout') diff --git a/packages/pg/test/unit/client/query-timeout-tests.js b/packages/pg/test/unit/client/query-timeout-tests.js new file mode 100644 index 000000000..dbf20cf1f --- /dev/null +++ b/packages/pg/test/unit/client/query-timeout-tests.js @@ -0,0 +1,34 @@ +'use strict' + +const helper = require('./test-helper') +const Query = require('../../../lib/query') +const assert = require('assert') +const suite = new helper.Suite() +const test = suite.test.bind(suite) + +test('query timeout with Submittable without callback delivers error via handleError', function (done) { + const client = helper.client() + client.connectionParameters = { query_timeout: 10 } + + const query = new Query({ text: 'SELECT 1' }) + query.handleError = (err) => { + assert.equal(err.message, 'Query read timeout') + done() + } + + client.connection.emit('readyForQuery') + client.query(query) +}) + +test('query timeout with Submittable with callback delivers error via callback', function (done) { + const client = helper.client() + client.connectionParameters = { query_timeout: 10 } + + const query = new Query({ text: 'SELECT 1' }) + client.connection.emit('readyForQuery') + + client.query(query, (err) => { + assert.equal(err.message, 'Query read timeout') + done() + }) +})