Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions packages/pg-cloudflare/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,22 +87,24 @@ export class CloudflareSocket extends EventEmitter {
write(
data: Uint8Array | string,
encodingOrCallback: BufferEncoding | ((error?: unknown) => void) = 'utf8',
callback: (error?: unknown) => void = () => {}
callback?: (error?: unknown) => void
): true | void {
const encoding = typeof encodingOrCallback === 'function' ? 'utf8' : encodingOrCallback
if (typeof encodingOrCallback === 'function') callback = encodingOrCallback
if (data.length === 0) return callback()
if (data.length === 0) return callback?.()
if (typeof data === 'string') data = Buffer.from(data, encoding)

log('sending data direct:', data)
this._cfWriter!.write(data).then(
() => {
log('data sent')
callback()
callback?.()
},
(err) => {
log('send error', err)
callback(err)
// pg calls write() without a callback, so emit the error the way a net.Socket would
if (callback) callback(err)
else this.emit('error', err)
}
)
return true
Expand Down
31 changes: 31 additions & 0 deletions packages/pg-esm-test/pg-cloudflare.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,37 @@ describe('pg-cloudflare', () => {
await promise
})

it('should emit an error when a write without a callback fails', async () => {
const socket = new CloudflareSocket()
const writeError = new Error('write failed')
socket._cfWriter = { write: () => Promise.reject(writeError) }

const error = await new Promise((resolve, reject) => {
const timer = setTimeout(() => reject(new Error('error event was not emitted')), 100)
socket.once('error', (err) => {
clearTimeout(timer)
resolve(err)
})
socket.write(Buffer.from('x'))
})
assert.equal(error, writeError)
})

it('should pass a failed write to the callback instead of emitting an error', async () => {
const socket = new CloudflareSocket()
const writeError = new Error('write failed')
socket._cfWriter = { write: () => Promise.reject(writeError) }
let emitted = false
socket.on('error', () => {
emitted = true
})

const error = await new Promise((resolve) => socket.write(Buffer.from('x'), resolve))
assert.equal(error, writeError)
await new Promise((resolve) => setTimeout(resolve, 10))
assert.equal(emitted, false)
})

it('should emit close when ending a socket whose closed promise never settles', async () => {
const socket = new CloudflareSocket()
socket._cfSocket = {
Expand Down
Loading