Pools insufficient demand to initialize
LupusUmbrae opened this issue · 9 comments
Hello,
We're having an odd issue when using the pool (see debug output below).
After awhile we start to see database queries just not running (VisualVM confirms no JDBC activity other than the database ping. It looks as though the pool is getting stuck but we're really not sure how/why. It does appear to recover after a period of time
Currently trying to reproduce this in a small simple test
This is the output we get when the database activity stops
09:51:44.065 [mcl-4] DEBUG org.davidmoten.rx.pool.MemberSingle - subscribed
09:51:44.065 [mcl-4] DEBUG org.davidmoten.rx.pool.MemberSingle - drain called
09:51:44.065 [mcl-4] DEBUG org.davidmoten.rx.pool.MemberSingle - drain loop starting
09:51:44.065 [mcl-4] DEBUG org.davidmoten.rx.pool.MemberSingle - requested=2
09:51:44.065 [mcl-4] DEBUG org.davidmoten.rx.pool.MemberSingle - poll of available members returns null
09:51:44.065 [mcl-4] DEBUG org.davidmoten.rx.pool.MemberSingle - scheduling member creation
09:51:44.065 [mcl-4] DEBUG org.davidmoten.rx.pool.MemberSingle - poll of available members returns null
09:51:44.065 [mcl-4] DEBUG org.davidmoten.rx.pool.MemberSingle - insufficient demand to initialize DecoratingMember [value=null]
What we normally get when working
09:51:44.065 [mcl-1] DEBUG org.davidmoten.rx.pool.MemberSingle - subscribed
09:51:44.065 [mcl-1] DEBUG org.davidmoten.rx.pool.MemberSingle - drain called
09:51:44.065 [mcl-1] DEBUG org.davidmoten.rx.pool.MemberSingle - drain loop starting
09:51:44.065 [mcl-1] DEBUG org.davidmoten.rx.pool.MemberSingle - requested=1
09:51:44.065 [mcl-1] DEBUG org.davidmoten.rx.pool.MemberSingle - poll of available members returns DecoratingMember [value=conn21: url=jdbc:h2:tcp://localhost:9123/Primary-SCDBSIM user=SA]
09:51:44.065 [mcl-1] DEBUG org.davidmoten.rx.pool.MemberSingle - trying to emit member
09:51:44.065 [mcl-1] DEBUG org.davidmoten.rx.pool.MemberSingle - schedule.now=1521193904065, lastCheck=1521193904060
09:51:44.065 [mcl-1] DEBUG org.davidmoten.rx.pool.MemberSingle - no health check required for DecoratingMember [value=conn21: url=jdbc:h2:tcp://localhost:9123/dbname user=SA]
Pool configuration
Pools.nonBlocking().url(url).scheduler(Schedulers.from(executorService))
.maxIdleTime(0, TimeUnit.MINUTES).healthCheck(c -> {
try {
return c.prepareStatement("select 1").execute();
} catch (SQLException e) {
LOG.debug("SQLException Occurred whilst invoking a health check on the database", e);
}
return false;
}).idleTimeBeforeHealthCheck(1, TimeUnit.SECONDS).maxPoolSize(100).build();
I have tried adjusting the above idle times and pool size but it doesn't appear to have any effect.
The executor service has 10 threads.
Any help/thoughts would be appreciated. We'll keep working to get you a test case for it as well.
Note we are using 0.1-rc19, so going to grab the latest version and test it again..
Just tried with RC32 and get the same problem;
10:34:14.668 [mcl-9] DEBUG org.davidmoten.rx.jdbc.SqlInfo - sqlAfterSubs=SELECT TOP 1 table1.col AS "col", at.col1, at.col2, sa.col3 FROM schema.table2 AS at INNER JOIN schema.table3 AS bm ON at.col1=bm.Name INNER JOIN schema.table1 AS table1 ON bm.Name=table1.col INNER JOIN schema.table2 AS sa ON at.col2=sa.col2 WHERE table1.col=? AND sa.col3=?
10:34:14.668 [mcl-9] DEBUG org.davidmoten.rx.pool.MemberSingle - subscribed
10:34:14.668 [mcl-9] DEBUG org.davidmoten.rx.pool.MemberSingle - drain called
10:34:14.668 [mcl-9] DEBUG org.davidmoten.rx.pool.MemberSingle - drain loop starting
10:34:14.668 [mcl-9] DEBUG org.davidmoten.rx.pool.MemberSingle - requested=4
10:34:14.668 [mcl-9] DEBUG org.davidmoten.rx.pool.MemberSingle - poll of available members returns null
Thanks for the report. I'll have a look soon keeping an eye out for possible stalls.
I've
- reduced complexity by grouping
requested
with theobservers
array to ensure they are changed together atomically - called
drain()
after removal of an observer fromobservers
to ensure no stall occurs
Please give 0.1-RC33 a go (available on Maven Central in about 10 minutes).
Ah, hold off on Rc33, I don't think I finished the job.
Yep, finished the review (just checking the insufficient demand part). Please try 0.1-RC33.
Doesn't seem to have fixed our issue, however I've had a closer look and it appears the issue only occurs if we using a blocking call somewhere down the line.
In this case we're calling a method that subsequently requests several hundred database queries but eventually calls a blockingForEach
. If we switch this to just a forEach
it appears to run ok (just testing it now).
With the blocking operation we get the following output;
10:38:03.272 [TP-2] DEBUG org.davidmoten.rx.jdbc.Util - closing org.davidmoten.rx.jdbc.pool.internal.ConnectionNonBlockingMemberPreparedStatement@53504604
10:38:03.272 [TP-2] DEBUG org.davidmoten.rx.jdbc.Util - closing org.davidmoten.rx.jdbc.pool.internal.PooledConnection@16cfcd5a
10:38:03.272 [TP-2] DEBUG org.davidmoten.rx.pool.MemberSingle - checking in DecoratingMember [value=conn3: url=jdbc:h2:tcp://localhost:9123/Primary-SCDBSIM user=SA]
10:38:03.272 [TP-2] DEBUG org.davidmoten.rx.pool.MemberSingle - drain called
10:38:03.272 [TP-2] DEBUG org.davidmoten.rx.pool.MemberSingle - drain loop starting
10:38:03.272 [TP-2] DEBUG org.davidmoten.rx.pool.MemberSingle - requested=7
10:38:03.272 [TP-2] DEBUG org.davidmoten.rx.pool.MemberSingle - poll of available members returns DecoratingMember [value=conn3: url=jdbc:h2:tcp://localhost:9123/Primary-SCDBSIM user=SA]
10:38:03.272 [TP-2] DEBUG org.davidmoten.rx.pool.MemberSingle - trying to emit member
10:38:03.272 [TP-2] DEBUG org.davidmoten.rx.pool.MemberSingle - schedule.now=1521628683272, lastCheck=1521628683272
10:38:03.272 [TP-2] DEBUG org.davidmoten.rx.pool.MemberSingle - no health check required for DecoratingMember [value=conn3: url=jdbc:h2:tcp://localhost:9123/Primary-SCDBSIM user=SA]
10:38:03.272 [TP-2] DEBUG org.davidmoten.rx.pool.MemberSingle - poll of available members returns null
10:38:03.272 [TP-2] DEBUG org.davidmoten.rx.jdbc.Util - closing rs97: null
10:38:03.286 [RxCachedThreadScheduler-1] DEBUG org.davidmoten.rx.pool.MemberSingle - subscribed
10:38:03.286 [RxCachedThreadScheduler-1] DEBUG org.davidmoten.rx.pool.MemberSingle - drain called
10:38:03.286 [RxCachedThreadScheduler-1] DEBUG org.davidmoten.rx.pool.MemberSingle - drain loop starting
10:38:03.286 [RxCachedThreadScheduler-1] DEBUG org.davidmoten.rx.pool.MemberSingle - requested=7
10:38:03.286 [RxCachedThreadScheduler-1] DEBUG org.davidmoten.rx.pool.MemberSingle - poll of available members returns null
Ah yes, that could definitely get you into trouble. You might be able to call blockingForEach
if you call .subscribeOn(Schedulers.io()).blockingForEach()
so that you don't block one of the worker threads for the pool. Better still is to use forEach
.
Thanks.. trying to get all our blocking calls switched over.
Good conversation to have, I think I need to make a section in the README about the trouble we can get into with blocking.