From 9e1e1f9916a6a322148c1bb285c774fd7e3137d6 Mon Sep 17 00:00:00 2001 From: "robin.bygrave" Date: Thu, 20 Aug 2026 10:57:30 +1200 Subject: [PATCH] Progressively trim excess idle connections Limit each idle-trim cycle to roughly one quarter of the excess connections, reducing aggressive post-deployment connection close bursts. --- .../io/ebean/datasource/pool/FreeConnectionBuffer.java | 4 ++-- .../io/ebean/datasource/pool/PooledConnectionQueue.java | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ebean-datasource/src/main/java/io/ebean/datasource/pool/FreeConnectionBuffer.java b/ebean-datasource/src/main/java/io/ebean/datasource/pool/FreeConnectionBuffer.java index b593fb1..4cc6b93 100644 --- a/ebean-datasource/src/main/java/io/ebean/datasource/pool/FreeConnectionBuffer.java +++ b/ebean-datasource/src/main/java/io/ebean/datasource/pool/FreeConnectionBuffer.java @@ -60,10 +60,10 @@ void closeAll(boolean logErrors) { /** * Trim any inactive connections that have not been used since usedSince. */ - List trim(int minSize, long usedSince, long createdSince) { + List trim(int minSize, long usedSince, long createdSince, int maxTrim) { var trimmed = new ArrayList(); ListIterator iterator = freeBuffer.listIterator(minSize); - while (iterator.hasNext()) { + while (iterator.hasNext() && trimmed.size() < maxTrim) { PooledConnection pooledConnection = iterator.next(); if (pooledConnection.shouldTrim(usedSince, createdSince)) { iterator.remove(); diff --git a/ebean-datasource/src/main/java/io/ebean/datasource/pool/PooledConnectionQueue.java b/ebean-datasource/src/main/java/io/ebean/datasource/pool/PooledConnectionQueue.java index a43e963..fd78b76 100644 --- a/ebean-datasource/src/main/java/io/ebean/datasource/pool/PooledConnectionQueue.java +++ b/ebean-datasource/src/main/java/io/ebean/datasource/pool/PooledConnectionQueue.java @@ -526,10 +526,13 @@ private List trimInactiveConnections(long maxInactiveMillis, l if (freeList.size() > minSize) { // trim on maxInactive and maxAge long usedSince = System.currentTimeMillis() - maxInactiveMillis; - trimmedConnections = freeList.trim(minSize, usedSince, createdSince); + int excess = freeList.size() - minSize; + // Progressively reduce excess idle connections rather than closing them all at once. + int maxTrim = Math.max(1, (excess + 3) / 4); + trimmedConnections = freeList.trim(minSize, usedSince, createdSince, maxTrim); } else if (createdSince > 0) { // trim only on maxAge - trimmedConnections = freeList.trim(0, createdSince, createdSince); + trimmedConnections = freeList.trim(0, createdSince, createdSince, Integer.MAX_VALUE); } else { trimmedConnections = List.of(); }