diff --git a/packages/pg-cloudflare/src/index.ts b/packages/pg-cloudflare/src/index.ts index 527b433f5..d3900ef5f 100644 --- a/packages/pg-cloudflare/src/index.ts +++ b/packages/pg-cloudflare/src/index.ts @@ -126,9 +126,11 @@ export class CloudflareSocket extends EventEmitter { return this } - destroy(reason: string) { - log('destroying CF socket', reason) + destroy(error?: Error) { + log('destroying CF socket', error) this.destroyed = true + // Like net.Socket#destroy(error): 'error' with the reason, then 'close'. + if (error) queueMicrotask(() => this.emit('error', error)) return this.end() } diff --git a/packages/pg-esm-test/pg-cloudflare.test.js b/packages/pg-esm-test/pg-cloudflare.test.js index 683229158..eba8351e0 100644 --- a/packages/pg-esm-test/pg-cloudflare.test.js +++ b/packages/pg-esm-test/pg-cloudflare.test.js @@ -38,6 +38,47 @@ describe('pg-cloudflare', () => { await promise }) + it('should emit the destroy error before close', async () => { + const socket = new CloudflareSocket() + socket._cfSocket = { + closed: new Promise(() => {}), + close: async () => {}, + } + socket._addClosedHandler() + + const events = [] + const error = new Error('timeout expired') + socket.on('error', (emitted) => events.push(emitted)) + await new Promise((resolve) => { + socket.once('close', () => { + events.push('close') + resolve() + }) + socket.destroy(error) + }) + + assert.ok(socket.destroyed) + assert.deepEqual(events, [error, 'close']) + }) + + it('should not emit an error when destroyed without one', async () => { + const socket = new CloudflareSocket() + socket._cfSocket = { + closed: new Promise(() => {}), + close: async () => {}, + } + socket._addClosedHandler() + + const errors = [] + socket.on('error', (error) => errors.push(error)) + await new Promise((resolve) => { + socket.once('close', resolve) + socket.destroy() + }) + + assert.deepEqual(errors, []) + }) + it('should emit close when ending a socket whose closed promise never settles', async () => { const socket = new CloudflareSocket() socket._cfSocket = {