davidmoten/rxjava2-jdbc

Bug with MaxIdleTime

AChekroun opened this issue · 11 comments

When the parameter MaxIdleTime is used, idle connections are properly closed after the given duration. However, it seems they are not properly evicted from the pool (or re-connection does not happen). It results in a random ‘SocketException: Socket closed’ when one of those connections is used later on by the scheduler.

It seems the issue occurs only with specific values in configuration, such as :

Pool pool = Pools.nonBlocking()
.url(url)
.user(username)
.password(password)
.healthCheck(DatabaseType.POSTGRES)
.maxPoolSize(40)
.maxIdleTime(2, TimeUnit.MINUTES)
.idleTimeBeforeHealthCheck(5, TimeUnit.SECONDS)
.connectionRetryInterval(10, TimeUnit.SECONDS)
.build()

With different values, the problem will not occur.

Context :

Database : PGv9.6
Driver-PG : v42.2.5
RxJava2-jdbc : v0.2.4

Thanks for your time

Thanks, I'll have a look.

Back on to this now, sorry for the delay

I haven't reproduced this yet.

With different values, the problem will not occur.

What values will not bring about the problem?

When the parameter MaxIdleTime is used, idle connections are properly closed after the given duration. However, it seems they are not properly evicted from the pool (or re-connection does not happen)

Looks, this issue still exists. I use raw JDBC to connect to ORACLE and use member.checkin to release the connection back to pool after use. The MAXIDLETIME is set to 30mts, in my case. After 30mts of idle time, the INACTIVE connections are on rise. As explained earlier in the issue, believe the idle connections are not properly closed, leading to increase in INACTIVE connections

Ok, thanks. I'll check this.

I see unit test coverage of the max idle case. Can you show me your code please?

The set-up is similar to the one given in the initial issue raised with minor modification as below and the DB being Oracle -

NonBlockingConnectionPool pool = Pools.nonBlocking()
.connectionProvider(connectionProvider(dbUrl, userName, password))
.healthCheck(DatabaseType.ORACLE)
.maxPoolSize(40)
.maxIdleTime(30, TimeUnit.MINUTES)
.idleTimeBeforeHealthCheck(5, TimeUnit.SECONDS)
.connectionRetryInterval(10, TimeUnit.SECONDS)
.build()

Is there a way to check whether all the connections in the pool are exhausted after max idle time?

You can enable debug logging to see internal actions.

I've had a think about this and what i think might be happening is that checkin places the member on an MpscLinkedQueue for potential reuse which is a FIFO queue. If a FIFO queue is used then a burst of concurrent activity could create a bunch of live connections in the pool which if followed by sufficient checkouts and checkins from the pool before the idle timeout will mean that each member gets used at least once (round-robin style) before idle timeout reached. This keeps the number of live connections high even though the pool could shrink to a size of 1 in theory.

To support a shrinking connection pool that queue should be a LIFO queue. I'll knock up tests and a fix.

0.2.13 has the fix for this issue and is on Maven Central now. Please try it out. Thanks for your reports.