fix(db): open the pub/sub LISTEN connection outside the Hikari pool (#36934) - #36935
fix(db): open the pub/sub LISTEN connection outside the Hikari pool (#36934)#36935fabrizzio-dotCMS wants to merge 1 commit into
Conversation
…36934) `PGListener` borrowed a connection from the request pool and held it for the lifetime of the JVM, which is what a Postgres `LISTEN` needs and what a request pool must never hand out. Two consequences: the pool silently loses a slot that never shows up as in-use work, and HikariCP reports the hold as `Apparent connection leak detected` — a stack trace on every boot that reads like a bug and is not one, training everyone to ignore leak warnings. The listener now builds its own connection from the pool's JDBC coordinates via `DriverManager`, so the pool keeps its full capacity and the detector has nothing to report. When the datasource exposes no JDBC URL — JNDI-provided or otherwise wrapped — it falls back to the previous behaviour: a listener that works while logging a spurious warning beats no listener at all. Lifecycle is unchanged: `stopListening()` already closes the connection, so start/stop cycles do not accumulate connections. Tests: `JDBCPubSubListenerConnectionTest` pins both branches — the fallback returns the pooled connection, and a datasource with coordinates is never asked for one. 2/2 green, pure unit tests in no suite. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Claude finished @fabrizzio-dotCMS's task in 2m 27s —— View job Code ReviewI reviewed the diff against The approach is sound: opening a dedicated New Issues
Not blocking — the URL-only path is correct for the standard dotCMS Docker/env configuration confirmed in the PR's runtime test. Notes (non-blocking)
Overall this is a clean, well-scoped fix with good test coverage of the branch that matters. The only thing worth confirming before merge is the connection-properties question above. |
Controlled first-boot verification — cleanRe-ran the exact path where the warning was originally observed: empty database, so After 8 minutes of uptime — well past the 300 s default
Before the fix, the same stack logged the warning once per starter-load boot, with the stack trace rooted at Environment: PostgreSQL 18 ( |
|
Why are we doing this? The Hikari warning is noise. It’s not a real connection leak; it’s saying a possible connection leak. |
Fixes #36934
What
PGListenerborrowed a connection from the Hikari request pool and held it for the lifetime of the JVM:Holding it is correct — a Postgres
LISTENneeds a persistent connection — but taking it from the request pool is not. Two consequences:max_connections.Apparent connection leak detectedwith a stack trace rooted atPGListener.<init>. It is a false positive —stopListening()does release the connection — but it reads like a bug, and it trains operators and support to ignore leak warnings, including real ones.How
The listener builds its own connection from the pool's JDBC coordinates through
DriverManager, so the pool keeps its full capacity and the detector has nothing to report.When the datasource exposes no JDBC URL — JNDI-provided or otherwise wrapped — it falls back to the previous behaviour and says so in the log. A listener that works while logging a spurious warning beats no listener at all.
Lifecycle is unchanged:
stopListening()already closes the connection, so start/stop cycles do not accumulate connections.Testing
./mvnw test -pl :dotcms-core -Dmaven.build.cache.enabled=false \ -Dtest=JDBCPubSubListenerConnectionTestTests run: 2, Failures: 0, Errors: 0— pure unit tests, in no suite. They pin both branches: the fallback returns the pooled connection, and a datasource that does expose coordinates is never asked for one (verify(hikari, never()).getConnection()), which is the property that actually matters.Verified at runtime against PostgreSQL 18 + dotCMS in Docker:
A controlled first-boot run on an empty database — the path where the warning was originally observed, during the starter load — is in progress; I will post the result as a comment. What is already confirmed is the positive signal above: the dedicated path is taken and the listener starts and runs normally.
Context
Found incidentally while reproducing #36222 (TC-056) on a local ES→OS migration stack. Unrelated subsystem, so it is filed and fixed separately rather than bundled into that fix.
🤖 Generated with Claude Code