Skip to content

Commit bcbb956

Browse files
committed
Fix double readyForQuery
1 parent 0b9bb34 commit bcbb956

File tree

2 files changed

+57
-2
lines changed

2 files changed

+57
-2
lines changed

packages/pg-cursor/index.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,12 @@ Cursor.prototype.handleError = function (msg) {
155155
// only dispatch error events if we have a listener
156156
this.emit('error', msg)
157157
}
158-
// call sync to keep this connection from hanging
159-
this.connection.sync()
158+
// If we have already received a ready for query event do not double-sync
159+
// because this can cause a readyForQuery to be trigger a second time.
160+
if (this.state !== 'done') {
161+
// call sync to trigger a readyForQuery
162+
this.connection.sync()
163+
}
160164
}
161165

162166
Cursor.prototype._getRows = function (rows, cb) {

packages/pg-query-stream/test/error.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import assert from 'assert'
22
import helper from './helper'
33
import QueryStream from '../src'
4+
import { Pool, Client } from 'pg'
45

56
helper('error', function (client) {
67
it('receives error on stream', function (done) {
@@ -21,3 +22,53 @@ helper('error', function (client) {
2122
client.query('SELECT NOW()', done)
2223
})
2324
})
25+
26+
describe('error recovery', () => {
27+
// created from https://github.com/chrisdickinson/pg-test-case
28+
it('recovers from a streaming error in a transaction', async () => {
29+
const pool = new Pool()
30+
const client = await pool.connect()
31+
await client.query(`CREATE TEMP TABLE frobnicators (
32+
id serial primary key,
33+
updated timestamp
34+
)`)
35+
await client.query(`BEGIN;`)
36+
const query = new QueryStream(`INSERT INTO frobnicators ("updated") VALUES ($1) RETURNING "id"`, [Date.now()])
37+
let error: Error | undefined = undefined
38+
query.on('data', console.log).on('error', (e) => {
39+
error = e
40+
})
41+
client.query(query) // useless callback necessitated by an older version of honeycomb-beeline
42+
43+
await client.query(`ROLLBACK`)
44+
assert(error, 'Error should not be undefined')
45+
const { rows } = await client.query('SELECT NOW()')
46+
assert.strictEqual(rows.length, 1)
47+
client.release()
48+
const client2 = await pool.connect()
49+
await client2.query(`BEGIN`)
50+
client2.release()
51+
pool.end()
52+
})
53+
54+
// created from https://github.com/brianc/node-postgres/pull/2333
55+
it.skip('handles an error on a stream after a plain text non-stream error', async () => {
56+
const client = new Client()
57+
const stmt = 'SELECT * FROM goose;'
58+
await client.connect()
59+
return new Promise((resolve, reject) => {
60+
client.query(stmt).catch((e) => {
61+
assert(e, 'Query should have rejected with an error')
62+
const stream = new QueryStream('SELECT * FROM duck')
63+
client.query(stream)
64+
stream.on('error', () => {
65+
console.log('stream error')
66+
client.end((err) => {
67+
console.log('client ended')
68+
err ? reject(err) : resolve()
69+
})
70+
})
71+
})
72+
})
73+
})
74+
})

0 commit comments

Comments
 (0)