Skip to content

Commit 7627589

Browse files
authored
Merge pull request #112 from FOCONIS/recover-high-usage
Better recovery after reset on high pool load
2 parents 7ef074b + b026481 commit 7627589

File tree

2 files changed

+68
-11
lines changed

2 files changed

+68
-11
lines changed

ebean-datasource/src/main/java/io/ebean/datasource/pool/PooledConnectionQueue.java

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -227,18 +227,13 @@ private PooledConnection _obtainConnection() throws InterruptedException, SQLExc
227227
hitCount++;
228228
// are other threads already waiting? (they get priority)
229229
if (waitingThreads == 0) {
230-
PooledConnection freeConnection = extractFromFreeList();
231-
if (freeConnection != null) {
232-
return freeConnection;
230+
PooledConnection connection = extractFromFreeList();
231+
if (connection != null) {
232+
return connection;
233233
}
234-
if (busyList.size() < maxSize) {
235-
// grow the connection pool
236-
PooledConnection c = pool.createConnectionForQueue(connectionId++);
237-
int busySize = registerBusyConnection(c);
238-
if (Log.isLoggable(DEBUG)) {
239-
Log.debug("DataSource [{0}] grow; id[{1}] busy[{2}] max[{3}]", name, c.name(), busySize, maxSize);
240-
}
241-
return c;
234+
connection = createConnection();
235+
if (connection != null) {
236+
return connection;
242237
}
243238
}
244239
try {
@@ -258,13 +253,32 @@ private PooledConnection _obtainConnection() throws InterruptedException, SQLExc
258253
}
259254
}
260255

256+
private PooledConnection createConnection() throws SQLException {
257+
if (busyList.size() < maxSize) {
258+
// grow the connection pool
259+
PooledConnection c = pool.createConnectionForQueue(connectionId++);
260+
int busySize = registerBusyConnection(c);
261+
if (Log.isLoggable(DEBUG)) {
262+
Log.debug("DataSource [{0}] grow; id[{1}] busy[{2}] max[{3}]", name, c.name(), busySize, maxSize);
263+
}
264+
return c;
265+
} else {
266+
return null;
267+
}
268+
}
269+
261270
/**
262271
* Got into a loop waiting for connections to be returned to the pool.
263272
*/
264273
private PooledConnection _obtainConnectionWaitLoop() throws SQLException, InterruptedException {
265274
long nanos = MILLIS_TIME_UNIT.toNanos(waitTimeoutMillis);
266275
for (; ; ) {
267276
if (nanos <= 0) {
277+
// We waited long enough, that a connection was returned, so we try to create a new connection.
278+
PooledConnection conn = createConnection();
279+
if (conn != null) {
280+
return conn;
281+
}
268282
String msg = "Unsuccessfully waited [" + waitTimeoutMillis + "] millis for a connection to be returned."
269283
+ " No connections are free. You need to Increase the max connections of [" + maxSize + "]"
270284
+ " or look for a connection pool leak using datasource.xxx.capturestacktrace=true";
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package io.ebean.datasource.pool;
2+
3+
import io.ebean.datasource.DataSourceBuilder;
4+
import io.ebean.datasource.DataSourcePool;
5+
import org.junit.jupiter.api.Test;
6+
7+
import java.sql.Connection;
8+
import java.util.ArrayList;
9+
import java.util.List;
10+
import java.util.concurrent.ExecutorService;
11+
import java.util.concurrent.Executors;
12+
import java.util.concurrent.Future;
13+
14+
import static org.assertj.core.api.Assertions.assertThat;
15+
16+
public class ConnectionPoolRecoverTest {
17+
18+
@Test
19+
void testHeavyLoadPool() throws Exception {
20+
DataSourcePool pool = DataSourceBuilder.create()
21+
.url("jdbc:h2:mem:testConnectionPoolFull")
22+
.username("sa")
23+
.password("sa")
24+
.heartbeatFreqSecs(1)
25+
.minConnections(1)
26+
.maxConnections(1)
27+
.trimPoolFreqSecs(1)
28+
// .heartbeatMaxPoolExhaustedCount(1)
29+
.failOnStart(false)
30+
.build();
31+
try {
32+
for (int i = 0; i < 5; i++) {
33+
try (Connection conn = pool.getConnection()) {
34+
Thread.sleep(2000);
35+
conn.rollback();
36+
}
37+
}
38+
} finally {
39+
pool.shutdown();
40+
}
41+
}
42+
43+
}

0 commit comments

Comments
 (0)