-
Couldn't load subscription status.
- Fork 3.9k
Description
Expected behavior
My primary use case for redis cluster at the moment is as an in-memory cache. Ideally, if redis wasn't available, or if the jedis pool was too busy, we'd just fail immediately and fall back to reading data from our persistent data store.
In particular, I'm running with:
JedisPoolConfig config = new JedisPoolConfig();
// ... stuff
config.setBlockWhenExhausted(false);
My hope was that in this configuration, if my java app was already using all of its connections, the new attempt to use the connection would error immediately, and I could catch that error and treat it as if the value didn't exist in the cache and just serve it from our persistent store.
Actual behavior
What is actually happening is that when there aren't any available Jedis instances available, the underlying GenericObjectPool pool is doing throw new NoSuchElementException("Pool exhausted");, and Jedis is catching that exception and wrapping it in a JedisConnectionException: "Could not get a resource from the pool". That exception is then caught at JedisClusterCommand:~120, and is treated the same as if the cluster is unreachable, or if a MOVED response was received. The NoSuchElementException, and Could not get a resources from the pool exceptions are also caught without logging, which made it more difficult to debug this issue.
I don't think this issue will show up with the default JedisPoolConfig object, because it has blockWhenExhausted=true and maxWaitMillis=-1, so it will just wait indefinitely.
Steps to reproduce:
For a guaranteed repro, set JedisPoolConfig:
config.setBlockWhenExhausted(false);
config.setMaxTotal(1);
and then issue calls to jedis in parallel.
(I don't have a working reduced repro case handy, but if it would be helpful I'm happy to whip one up.)
Redis / Jedis Configuration
Jedis version:
3.0.6
Redis version:
2.8.0
Java version:
JDK 8
Thanks!