From e3b79ee044a3c0de4ec47187250879edbb9b1f79 Mon Sep 17 00:00:00 2001 From: Brett Wooldridge Date: Tue, 29 Nov 2016 09:05:50 +0900 Subject: [PATCH] =?UTF-8?q?Fixes=20#770=20by=20adding=20a=20new=20property?= =?UTF-8?q?=20initializationFailTimeout=20and=20deprecating=20initializati?= =?UTF-8?q?onFailFast.=20=20Exception=20path=20still=20needs=20some=20work?= =?UTF-8?q?=E2=80=A6=20coming=20in=20the=20next=20commit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/zaxxer/hikari/HikariConfig.java | 36 +++++++++++++++++++ .../com/zaxxer/hikari/pool/HikariPool.java | 21 ++++++++--- .../zaxxer/hikari/pool/TestConnections.java | 2 +- 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/zaxxer/hikari/HikariConfig.java b/src/main/java/com/zaxxer/hikari/HikariConfig.java index 030ac24e..9589e4e2 100644 --- a/src/main/java/com/zaxxer/hikari/HikariConfig.java +++ b/src/main/java/com/zaxxer/hikari/HikariConfig.java @@ -69,6 +69,7 @@ public class HikariConfig implements HikariConfigMXBean // Properties NOT changeable at runtime // + private long initializationFailTimeout; private String catalog; private String connectionInitSql; private String connectionTestQuery; @@ -393,12 +394,42 @@ public class HikariConfig implements HikariConfigMXBean this.isAllowPoolSuspension = isAllowPoolSuspension; } + /** + * Get the pool initialization failure timeout. + * + * @return the number of milliseconds before the pool initialization fails + */ + public long getInitializationFailTimeout() + { + return initializationFailTimeout; + } + + /** + * Set the pool initialization failure timeout. A value of 0 (default) fails immediately. + * The minimum value is 1000ms (1 second). + * + * @param initializationFailTimeout the number of milliseconds before the + * pool initialization fails + */ + public void setInitializationFailTimeout(long initializationFailTimeout) + { + if (initializationFailTimeout < 0L) { + initializationFailTimeout = 0L; + } + else if (initializationFailTimeout < 1000L) { + initializationFailTimeout = 1000L; + } + + this.initializationFailTimeout = initializationFailTimeout; + } + /** * Get whether or not the construction of the pool should throw an exception * if the minimum number of connections cannot be created. * * @return whether or not initialization should fail on error immediately */ + @Deprecated public boolean isInitializationFailFast() { return isInitializationFailFast; @@ -410,9 +441,14 @@ public class HikariConfig implements HikariConfigMXBean * * @param failFast true if the pool should fail if the minimum connections cannot be created */ + @Deprecated public void setInitializationFailFast(boolean failFast) { isInitializationFailFast = failFast; + LOGGER.warn("The initializationFailFast propery is deprecated, see initializationFailTimeout"); + if (!failFast) { + initializationFailTimeout = Long.MAX_VALUE; + } } public boolean isIsolateInternalQueries() diff --git a/src/main/java/com/zaxxer/hikari/pool/HikariPool.java b/src/main/java/com/zaxxer/hikari/pool/HikariPool.java index 46a3f0b9..c57b1c4e 100644 --- a/src/main/java/com/zaxxer/hikari/pool/HikariPool.java +++ b/src/main/java/com/zaxxer/hikari/pool/HikariPool.java @@ -27,6 +27,7 @@ import static java.util.concurrent.TimeUnit.SECONDS; import java.sql.Connection; import java.sql.SQLException; +import java.sql.SQLTimeoutException; import java.sql.SQLTransientConnectionException; import java.util.List; import java.util.concurrent.Callable; @@ -507,16 +508,28 @@ public class HikariPool extends PoolBase implements HikariPoolMXBean, IBagStateL */ private void checkFailFast() { - if (config.isInitializationFailFast()) { + if (config.getInitializationFailTimeout() == 0) { + return; + } + + final long startTime = clockSource.currentTime(); + boolean acquired = false; + Throwable throwable = new SQLTimeoutException("HikariCP was unable to initialize connections in pool " + poolName); + do { try (Connection connection = newConnection()) { + acquired = true; if (!connection.getAutoCommit()) { connection.commit(); } + return; } - catch (Throwable e) { - throw new PoolInitializationException(e); + catch (Throwable t) { + throwable = t; + quietlySleep(1000L); } - } + } while (!acquired && clockSource.elapsedMillis(startTime) < config.getInitializationFailTimeout()); + + throw new PoolInitializationException(throwable); } private void softEvictConnection(final PoolEntry poolEntry, final String reason, final boolean owner) diff --git a/src/test/java/com/zaxxer/hikari/pool/TestConnections.java b/src/test/java/com/zaxxer/hikari/pool/TestConnections.java index 003ae930..f5bd4e4d 100644 --- a/src/test/java/com/zaxxer/hikari/pool/TestConnections.java +++ b/src/test/java/com/zaxxer/hikari/pool/TestConnections.java @@ -500,7 +500,7 @@ public class TestConnections config.setMaximumPoolSize(2); config.setConnectionTimeout(TimeUnit.SECONDS.toMillis(3)); config.setConnectionTestQuery("VALUES 1"); - config.setInitializationFailFast(false); + config.setInitializationFailTimeout(TimeUnit.SECONDS.toMillis(2)); config.setDataSource(stubDataSource); try (HikariDataSource ds = new HikariDataSource(config); Connection c = ds.getConnection()) {