Skip to content

Commit e43f307

Browse files
committed
Add onidle callback option - fixes #1100
1 parent 5c8135f commit e43f307

File tree

3 files changed

+107
-1
lines changed

3 files changed

+107
-1
lines changed

src/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ function Postgres(a, b) {
310310
queue.push(c)
311311
c.queue = queue
312312
queue === open
313-
? c.idleTimer.start()
313+
? (c.idleTimer.start(), options.onidle && options.onidle(c.id))
314314
: c.idleTimer.cancel()
315315
return c
316316
}
@@ -492,6 +492,7 @@ function parseOptions(a, b) {
492492
onnotify : o.onnotify,
493493
onclose : o.onclose,
494494
onparameter : o.onparameter,
495+
onidle : o.onidle,
495496
socket : o.socket,
496497
transform : parseTransform(o.transform || { undefined: undefined }),
497498
parameters : {},

tests/index.js

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -959,6 +959,107 @@ t('responds with server parameters (application_name)', async() =>
959959
})`select 1`.catch(reject))]
960960
)
961961

962+
t('onidle fires for each connection in pool', async() => {
963+
const ids = []
964+
const sql = postgres({
965+
...options,
966+
max: 2,
967+
onidle: (id) => ids.push(id)
968+
})
969+
970+
// Run two queries concurrently to use both connections.
971+
await Promise.all([
972+
sql`select pg_sleep(0.05)`,
973+
sql`select pg_sleep(0.05)`
974+
])
975+
await sql.end()
976+
977+
// Both connections should have fired onidle.
978+
return [2, ids.length]
979+
})
980+
981+
t('onidle not called when queries are queued', async() => {
982+
let idleCount = 0
983+
const sql = postgres({
984+
...options,
985+
max: 1,
986+
onidle: () => idleCount++
987+
})
988+
989+
// Run two queries concurrently on single connection.
990+
await Promise.all([
991+
sql`select pg_sleep(0.05)`,
992+
sql`select 1`
993+
])
994+
await sql.end()
995+
996+
// Should only fire once after both queries complete and connection returns to idle.
997+
return [1, idleCount]
998+
})
999+
1000+
t('onidle receives connection id', async() => {
1001+
const ids = []
1002+
const sql = postgres({
1003+
...options,
1004+
max: 2,
1005+
onidle: (id) => ids.push(id)
1006+
})
1007+
1008+
// Use two connections.
1009+
await Promise.all([
1010+
sql`select pg_sleep(0.05)`,
1011+
sql`select pg_sleep(0.05)`
1012+
])
1013+
await sql.end()
1014+
1015+
// Should receive valid integer ids, and they should be different.
1016+
return [true, ids.length === 2 && ids.every(Number.isInteger) && ids[0] !== ids[1]]
1017+
})
1018+
1019+
t('onidle can be set after creation', async() => {
1020+
let called = false
1021+
const sql = postgres({ ...options, max: 1 })
1022+
1023+
sql.options.onidle = () => called = true
1024+
1025+
await sql`select 1`
1026+
await sql.end()
1027+
1028+
return [true, called]
1029+
})
1030+
1031+
t('onidle fires after reserved connection is released', async() => {
1032+
let idleCount = 0
1033+
const sql = postgres({
1034+
...options,
1035+
max: 1,
1036+
onidle: () => idleCount++
1037+
})
1038+
1039+
const reserved = await sql.reserve()
1040+
await reserved`select 1`
1041+
reserved.release()
1042+
await sql.end()
1043+
1044+
return [1, idleCount]
1045+
})
1046+
1047+
t('onidle fires after transaction completes', async() => {
1048+
let idleCount = 0
1049+
const sql = postgres({
1050+
...options,
1051+
max: 1,
1052+
onidle: () => idleCount++
1053+
})
1054+
1055+
await sql.begin(async sql => {
1056+
await sql`select 1`
1057+
})
1058+
await sql.end()
1059+
1060+
return [1, idleCount]
1061+
})
1062+
9621063
t('has server parameters', async() => {
9631064
return ['postgres.js', (await sql`select 1`.then(() => sql.parameters.application_name))]
9641065
})

types/index.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,10 @@ interface BaseOptions<T extends Record<string, postgres.PostgresType>> {
119119
*/
120120
publications: string
121121
onclose: (connId: number) => void;
122+
/**
123+
* Called when a connection returns to the pool after completing queries
124+
*/
125+
onidle: (connId: number) => void;
122126
backoff: boolean | ((attemptNum: number) => number);
123127
max_lifetime: number | null;
124128
keep_alive: number | null;

0 commit comments

Comments
 (0)