diff --git a/lib-jedis-pool/README.md b/lib-jedis-pool/README.md index 29d82750..2901709a 100644 --- a/lib-jedis-pool/README.md +++ b/lib-jedis-pool/README.md @@ -16,7 +16,7 @@ dependencies { - Full Redis URI parsing including database selection (`redis://host:6379/1`) - SSL/TLS support (`rediss://` scheme) -- Configurable connection pool (minIdle, maxIdle, maxTotal) +- Configurable connection pool (minIdle, maxIdle, maxTotal, testOnBorrow) - Optional password override via configuration - Micrometer metrics integration (when MeterRegistry is available) - Conditional activation via RedisActivator @@ -31,6 +31,7 @@ redis: minIdle: 0 # Default: 0 maxIdle: 10 # Default: 10 maxTotal: 50 # Default: 50 + testOnBorrow: false # Default: false — PING-validate connections on borrow client: timeout: 5000 # Default: 5000ms ``` diff --git a/lib-jedis-pool/VERSION b/lib-jedis-pool/VERSION index afaf360d..9084fa2f 100644 --- a/lib-jedis-pool/VERSION +++ b/lib-jedis-pool/VERSION @@ -1 +1 @@ -1.0.0 \ No newline at end of file +1.1.0 diff --git a/lib-jedis-pool/changelog.txt b/lib-jedis-pool/changelog.txt index 6e863bdb..780295e4 100644 --- a/lib-jedis-pool/changelog.txt +++ b/lib-jedis-pool/changelog.txt @@ -1,5 +1,8 @@ # lib-jedis-pool changelog +1.1.0 - 21 Jul 2026 +- Add redis.pool.testOnBorrow option to PING-validate connections on borrow and evict RESP-desynced connections + 1.0.0 - 12 Jan 2026 - Initial release of lib-jedis-pool extracted from Wave project - Add JedisPoolFactory for creating configured JedisPool beans diff --git a/lib-jedis-pool/src/main/java/io/seqera/jedis/JedisPoolFactory.java b/lib-jedis-pool/src/main/java/io/seqera/jedis/JedisPoolFactory.java index 3bbe43b1..03e243d5 100644 --- a/lib-jedis-pool/src/main/java/io/seqera/jedis/JedisPoolFactory.java +++ b/lib-jedis-pool/src/main/java/io/seqera/jedis/JedisPoolFactory.java @@ -61,6 +61,7 @@ public JedisPool createRedisPool( @Value("${redis.pool.minIdle:0}") int minIdle, @Value("${redis.pool.maxIdle:10}") int maxIdle, @Value("${redis.pool.maxTotal:50}") int maxTotal, + @Value("${redis.pool.testOnBorrow:false}") boolean testOnBorrow, @Value("${redis.client.timeout:5000}") int timeout, @Nullable @Value("${redis.password}") String password ) { @@ -70,14 +71,17 @@ public JedisPool createRedisPool( } final int database = JedisURIHelper.getDBIndex(uri); - log.info("Creating Redis pool - uri={}; database={}; minIdle={}; maxIdle={}; maxTotal={}; timeout={}", - maskPassword(connection), database, minIdle, maxIdle, maxTotal, timeout); + log.info("Creating Redis pool - uri={}; database={}; minIdle={}; maxIdle={}; maxTotal={}; testOnBorrow={}; timeout={}", + maskPassword(connection), database, minIdle, maxIdle, maxTotal, testOnBorrow, timeout); // Pool config final JedisPoolConfig config = new JedisPoolConfig(); config.setMinIdle(minIdle); config.setMaxIdle(maxIdle); config.setMaxTotal(maxTotal); + // PING-validate connections on borrow so a RESP-desynced connection is evicted + // instead of served to the next caller — see libseqera#92 / platform#11820 + config.setTestOnBorrow(testOnBorrow); // Client config with database support final JedisClientConfig clientConfig = clientConfig(uri, password, timeout); diff --git a/lib-jedis-pool/src/test/groovy/io/seqera/jedis/JedisPoolFactoryTest.groovy b/lib-jedis-pool/src/test/groovy/io/seqera/jedis/JedisPoolFactoryTest.groovy index debe77a6..28884ec5 100644 --- a/lib-jedis-pool/src/test/groovy/io/seqera/jedis/JedisPoolFactoryTest.groovy +++ b/lib-jedis-pool/src/test/groovy/io/seqera/jedis/JedisPoolFactoryTest.groovy @@ -33,7 +33,7 @@ class JedisPoolFactoryTest extends Specification { def factory = new JedisPoolFactory(meterRegistry: Mock(MeterRegistry)) when: - def pool = factory.createRedisPool(URI_STRING, MIN_IDLE, MAX_IDLE, MAX_TOTAL, TIMEOUT, 'password') + def pool = factory.createRedisPool(URI_STRING, MIN_IDLE, MAX_IDLE, MAX_TOTAL, false, TIMEOUT, 'password') then: pool != null @@ -75,7 +75,7 @@ class JedisPoolFactoryTest extends Specification { def factory = new JedisPoolFactory(meterRegistry: Mock(MeterRegistry)) when: - factory.createRedisPool(URI_STRING, 0, 10, 50, 5000, null) + factory.createRedisPool(URI_STRING, 0, 10, 50, false, 5000, null) then: def e = thrown(InvalidURIException) @@ -87,12 +87,29 @@ class JedisPoolFactoryTest extends Specification { 'localhost:6379' | _ } + def 'should enable testOnBorrow on the pool config'() { + given: + def factory = new JedisPoolFactory() + + when: + def pool = factory.createRedisPool('redis://localhost:6379', 0, 10, 50, ON_BORROW, 5000, null) + + then: + pool.testOnBorrow == ON_BORROW + + cleanup: + pool?.close() + + where: + ON_BORROW << [true, false] + } + def 'should create pool without meter registry'() { given: def factory = new JedisPoolFactory() when: - def pool = factory.createRedisPool('redis://localhost:6379', 0, 10, 50, 5000, null) + def pool = factory.createRedisPool('redis://localhost:6379', 0, 10, 50, false, 5000, null) then: pool != null