Behaviour of Hikari setConnectionTimeout

8.6k Views Asked by At

Just looking for an explanation of rationale for this bit of code (PoolUtiltites:293 in version 2.2.4):

dataSource.setLoginTimeout((int) TimeUnit.MILLISECONDS.toSeconds(Math.min(1000L, connectionTimeout)));

This code and the setConnectionTimeout method means that I get this behaviour:

  • connectionTimeout == 0, then loginTimeout = Integer.MAX_VALUE
  • connectionTimeout > 0 && < 100, then HikariConfig throws IllegalArgumentException
  • connectionTimeout >= 100 && <= 1000, then loginTimeout = connectionTimeout
  • connectionTeimout > 1000, then loginTimeout = 1000

That looks really weird to me!

It's almost like the Math.min should be Math.max ???

In my current project I'd like to fail connections after 30s, which is impossible in the current setup.

I'm using the 4.1 postgres jdbc driver, but I think this is not relevant to the issue above.

Many thanks - and cool pooling library!!!

1

There are 1 best solutions below

2
On BEST ANSWER

Ok, there are a couple of moving parts here. First, Math.min() is a bug, it should be Math.max(). In light of that (it will be fixed) consider the following:

It is important to note that connections are created asynchronously in the pool. The setConnectionTimeout() sets the maximum time (in milliseconds) that a call to getConnection() will wait for a connection before timing out.

The DataSource loginTimeout is the maximum time that physical connection initiation to the database can take before timing out. Because HikariCP obtains connections asynchronously, if the connection attempt fails, HikariCP will continue to retry, but your calls to getConnection() will timeout appropriately. We are using the connectionTimeout in kind of a double duty for loginTimeout.

For example, lets say the pool is completely empty, and you have configured a connectionTimeout of 30 seconds. When you call getConnection() HikariCP, realizing that there are no idle connections available, starts trying to obtain a new one. There is little point in having a loginTimeout exceeding 30 seconds, in this case.

The intent of the Math.max() call is to ensure that we never set loginTimeout to 0 if the user has configured connectionTimeout to 250ms. TimeUnit.MILLESECONDS.toSeconds() would return 0 without the Math.max(). If the user has configured a connectionTimeout of 0, meaning they never want to timeout, the time conversion of Integer.MAX_VALUE results in several thousand years as a timeout (virtually never).

Having said that, and in light of how HikariCP connections to the database are obtained asynchronously, even without the Math.max() fix, you should be able to achieve application-level connection timeouts of 30s. Unless physical connections to your database exceed 1000ms you would be unaffected by the Math.min().

We are putting out a 2.2.5-rc3 release candidate in the next few hours. I will slot this fix in.