I have analyzed the source code of HikariPool.java and identified a potential issue related to the thread pool configuration for addConnectionExecutor.
The addConnectionExecutor is responsible for creating new physical connections and adding them to the pool. Currently, it is configured with a CustomDiscardPolicy (which behaves similarly to DiscardPolicy).
Location
File: src/main/java/com/zaxxer/hikari/pool/HikariPool.java
Line: 118 (in the constructor)
Code:
this.addConnectionExecutor = createThreadPoolExecutor(maxPoolSize, poolName + ":connection-adder", threadFactory, new CustomDiscardPolicy());
Analysis In a high-concurrency scenario, if the addConnectionExecutor queue becomes full, the CustomDiscardPolicy will silently drop new PoolEntryCreator tasks.
Although addBagItem (line 412) attempts to check the queue size (if (waiting > addConnectionExecutor.getQueue().size())), a race condition or a sudden spike in requests could still result in the task submission being rejected by the policy.
If the task is discarded:
- No new connection is created.
- Threads waiting in connectionBag.borrow() will continue to wait until they timeout (SQLTransientConnectionException).
- The pool fails to expand to maximumPoolSize even though the database might be healthy.
This fits the DenyPolicySettingError (DPSE) pattern, where using a discard policy for critical resource production tasks leads to silent failures and resource starvation.
Suggested Fix Consider changing the rejection policy to CallerRunsPolicy or ensuring that the CustomDiscardPolicy provides a fallback mechanism (e.g., logging a warning or retrying) rather than silently ignoring the request.
Using CallerRunsPolicy would ensure that if the executor is busy, the calling thread (which is likely waiting for a connection anyway) assists in creating the connection, thus preventing task loss.
// Suggested change:
this.addConnectionExecutor = createThreadPoolExecutor(maxPoolSize, poolName + ":connection-adder", threadFactory, new ThreadPoolExecutor.CallerRunsPolicy());
Environment
HikariCP version: (Master)
JDK version: 1.8
I have analyzed the source code of HikariPool.java and identified a potential issue related to the thread pool configuration for addConnectionExecutor.
The addConnectionExecutor is responsible for creating new physical connections and adding them to the pool. Currently, it is configured with a CustomDiscardPolicy (which behaves similarly to DiscardPolicy).
Location
File: src/main/java/com/zaxxer/hikari/pool/HikariPool.java
Line: 118 (in the constructor)
Code:
this.addConnectionExecutor = createThreadPoolExecutor(maxPoolSize, poolName + ":connection-adder", threadFactory, new CustomDiscardPolicy());
Analysis In a high-concurrency scenario, if the addConnectionExecutor queue becomes full, the CustomDiscardPolicy will silently drop new PoolEntryCreator tasks.
Although addBagItem (line 412) attempts to check the queue size (if (waiting > addConnectionExecutor.getQueue().size())), a race condition or a sudden spike in requests could still result in the task submission being rejected by the policy.
If the task is discarded:
This fits the DenyPolicySettingError (DPSE) pattern, where using a discard policy for critical resource production tasks leads to silent failures and resource starvation.
Suggested Fix Consider changing the rejection policy to CallerRunsPolicy or ensuring that the CustomDiscardPolicy provides a fallback mechanism (e.g., logging a warning or retrying) rather than silently ignoring the request.
Using CallerRunsPolicy would ensure that if the executor is busy, the calling thread (which is likely waiting for a connection anyway) assists in creating the connection, thus preventing task loss.
// Suggested change:
this.addConnectionExecutor = createThreadPoolExecutor(maxPoolSize, poolName + ":connection-adder", threadFactory, new ThreadPoolExecutor.CallerRunsPolicy());
Environment
HikariCP version: (Master)
JDK version: 1.8