Problem
The abort handler in packages/postgres/src/mq.ts calls listen.unlisten() without awaiting or handling its Promise. The listening Promise can resolve while UNLISTEN is still pending. Closing the SQL client afterward can reject that request without a rejection handler.
This appears to explain a test-node failure on PR #1079 in PostgresMessageQueue continues processing when handler hangs (no ordering key):
failureType: 'unhandledRejection'
error: 'write CONNECTION_DESTROYED localhost:5432'
…
Object.unlisten (.../postgres/src/index.js:193:17)
The test aborts the listener, awaits it, then drops the queue table and calls sql.end(). The PostgreSQL queue code was not changed by that PR.
Verification
On Node.js 22.23.1 with PostgreSQL 17.11, the test that failed in CI passed in 20 local runs. A separate probe wrapping the SQL client's listener handle confirmed that unlisten() was still pending after the queue's listening Promise resolved following an abort. The CI exception was not reproduced locally.
Expected behavior
Awaiting the listening Promise after abort should wait for UNLISTEN to finish and handle cleanup errors, so callers can safely close the SQL client.
A deterministic regression test should hold unlisten() pending and verify that the listening Promise waits for it, including the rejection path.
Problem
The abort handler in packages/postgres/src/mq.ts calls
listen.unlisten()without awaiting or handling its Promise. The listening Promise can resolve whileUNLISTENis still pending. Closing the SQL client afterward can reject that request without a rejection handler.This appears to explain a test-node failure on PR #1079 in
PostgresMessageQueue continues processing when handler hangs (no ordering key):The test aborts the listener, awaits it, then drops the queue table and calls
sql.end(). The PostgreSQL queue code was not changed by that PR.Verification
On Node.js 22.23.1 with PostgreSQL 17.11, the test that failed in CI passed in 20 local runs. A separate probe wrapping the SQL client's listener handle confirmed that
unlisten()was still pending after the queue's listening Promise resolved following an abort. The CI exception was not reproduced locally.Expected behavior
Awaiting the listening Promise after abort should wait for
UNLISTENto finish and handle cleanup errors, so callers can safely close the SQL client.A deterministic regression test should hold
unlisten()pending and verify that the listening Promise waits for it, including the rejection path.