Skip to content

Commit 09592ea

Browse files
committed
Fix listen reconnect on connection errors + simple backoff
1 parent d73338a commit 09592ea

File tree

2 files changed

+46
-8
lines changed

2 files changed

+46
-8
lines changed

lib/connection.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -352,13 +352,15 @@ function postgresSocket(options, {
352352
let next = null
353353
let buffer
354354
let i = 0
355+
let retries = 0
355356

356357
function onclose(err) {
358+
retries++
357359
oncleanup()
358360
!ended && !succeeded && i < options.host.length
359361
? connect()
360362
: err instanceof Error
361-
? error(err)
363+
? (error(err), close())
362364
: close()
363365
i >= options.host.length && (i = 0)
364366
}
@@ -373,10 +375,14 @@ function postgresSocket(options, {
373375
cleanup()
374376
}
375377

376-
function connect() {
378+
async function connect() {
377379
if (!closed)
378380
return
379381

382+
retries && await new Promise(r =>
383+
setTimeout(r, Math.min((0.5 + Math.random()) * Math.pow(1.3, retries) * 10, 10000))
384+
)
385+
380386
closed = succeeded = false
381387

382388
socket = options.path
@@ -419,6 +425,7 @@ function postgresSocket(options, {
419425
}
420426

421427
function ready() {
428+
retries = 0
422429
try {
423430
socket.write(frontend.StartupMessage(options))
424431
} catch (e) {
@@ -429,6 +436,7 @@ function postgresSocket(options, {
429436

430437
const x = {
431438
success: () => {
439+
retries = 0
432440
succeeded = true
433441
i >= options.host.length && (i = 0)
434442
},

tests/index.js

+36-6
Original file line numberDiff line numberDiff line change
@@ -574,12 +574,19 @@ t('listen and notify with weird name', async() => {
574574
)]
575575
})
576576

577-
t('listen and notify with upper case', async() =>
578-
['works', await new Promise(async resolve => {
579-
await sql.listen('withUpperChar', resolve)
580-
sql.notify('withUpperChar', 'works')
581-
})]
582-
)
577+
t('listen and notify with upper case', async() => {
578+
let result
579+
580+
const { unlisten } = await sql.listen('withUpperChar', x => result = x)
581+
sql.notify('withUpperChar', 'works')
582+
await delay(50)
583+
584+
return [
585+
'works',
586+
result,
587+
unlisten()
588+
]
589+
})
583590

584591
t('listen reconnects', async() => {
585592
const listener = postgres(options)
@@ -596,6 +603,29 @@ t('listen reconnects', async() => {
596603
return ['ab', xs.join('')]
597604
})
598605

606+
607+
t('listen reconnects after connection error', { timeout: 2000 }, async() => {
608+
const sql = postgres()
609+
, xs = []
610+
611+
const a = (await sql`show data_directory`)[0].data_directory
612+
613+
const { state: { pid } } = await sql.listen('test', x => xs.push(x))
614+
await sql.notify('test', 'a')
615+
await sql`select pg_terminate_backend(${ pid }::int)`
616+
617+
cp.execSync('pg_ctl stop -D "' + a + '"')
618+
await delay(50)
619+
cp.execSync('pg_ctl start -D "' + a + '" -w -l "' + a + '/postgresql.log"')
620+
await delay(50)
621+
622+
await sql.notify('test', 'b')
623+
await delay(50)
624+
sql.end()
625+
626+
return ['ab', xs.join('')]
627+
})
628+
599629
t('listen result reports correct connection state after reconnection', async() => {
600630
const listener = postgres(options)
601631
, xs = []

0 commit comments

Comments
 (0)