Polishing.

Prepare pool for Jedis as well. Introduce generics for Add ticket references to tests.

Fix generics for GenericObjectPoolConfig using Lettuce.

See #3072
This commit is contained in:
Mark Paluch
2025-01-10 14:01:05 +01:00
parent b7381ac6bb
commit 2bcdd36a36
6 changed files with 46 additions and 13 deletions

View File

@@ -730,6 +730,12 @@ public class JedisConnectionFactory
if (getUsePool() && !isRedisClusterAware()) {
this.pool = createPool();
try {
this.pool.preparePool();
} catch (Exception ex) {
throw new PoolException("Could not prepare the pool", ex);
}
}
if (isRedisClusterAware()) {

View File

@@ -18,6 +18,7 @@ package org.springframework.data.redis.connection.lettuce;
import io.lettuce.core.ClientOptions;
import io.lettuce.core.ReadFrom;
import io.lettuce.core.SslVerifyMode;
import io.lettuce.core.api.StatefulConnection;
import io.lettuce.core.resource.ClientResources;
import java.time.Duration;
@@ -37,10 +38,10 @@ import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
class DefaultLettucePoolingClientConfiguration implements LettucePoolingClientConfiguration {
private final LettuceClientConfiguration clientConfiguration;
private final GenericObjectPoolConfig poolConfig;
private final GenericObjectPoolConfig<StatefulConnection<?, ?>> poolConfig;
DefaultLettucePoolingClientConfiguration(LettuceClientConfiguration clientConfiguration,
GenericObjectPoolConfig poolConfig) {
GenericObjectPoolConfig<StatefulConnection<?, ?>> poolConfig) {
this.clientConfiguration = clientConfiguration;
this.poolConfig = poolConfig;
@@ -108,7 +109,7 @@ class DefaultLettucePoolingClientConfiguration implements LettucePoolingClientCo
}
@Override
public GenericObjectPoolConfig getPoolConfig() {
public GenericObjectPoolConfig<StatefulConnection<?, ?>> getPoolConfig() {
return poolConfig;
}
}

View File

@@ -17,6 +17,7 @@ package org.springframework.data.redis.connection.lettuce;
import io.lettuce.core.ClientOptions;
import io.lettuce.core.ReadFrom;
import io.lettuce.core.api.StatefulConnection;
import io.lettuce.core.resource.ClientResources;
import java.time.Duration;
@@ -39,7 +40,7 @@ public interface LettucePoolingClientConfiguration extends LettuceClientConfigur
/**
* @return the {@link GenericObjectPoolConfig}. Never {@literal null}.
*/
GenericObjectPoolConfig getPoolConfig();
GenericObjectPoolConfig<StatefulConnection<?, ?>> getPoolConfig();
/**
* Creates a new {@link LettucePoolingClientConfigurationBuilder} to build {@link LettucePoolingClientConfiguration}
@@ -91,7 +92,7 @@ public interface LettucePoolingClientConfiguration extends LettuceClientConfigur
*/
class LettucePoolingClientConfigurationBuilder extends LettuceClientConfigurationBuilder {
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
GenericObjectPoolConfig<StatefulConnection<?, ?>> poolConfig = new GenericObjectPoolConfig<>();
LettucePoolingClientConfigurationBuilder() {
super();
@@ -163,7 +164,8 @@ public interface LettucePoolingClientConfiguration extends LettuceClientConfigur
*
* @param poolConfig must not be {@literal null}.
*/
public LettucePoolingClientConfigurationBuilder poolConfig(GenericObjectPoolConfig poolConfig) {
public LettucePoolingClientConfigurationBuilder poolConfig(
GenericObjectPoolConfig<StatefulConnection<?, ?>> poolConfig) {
Assert.notNull(poolConfig, "PoolConfig must not be null");

View File

@@ -64,7 +64,7 @@ class LettucePoolingConnectionProvider implements LettuceConnectionProvider, Red
private static final Log log = LogFactory.getLog(LettucePoolingConnectionProvider.class);
private final LettuceConnectionProvider connectionProvider;
private final GenericObjectPoolConfig poolConfig;
private final GenericObjectPoolConfig<StatefulConnection<?, ?>> poolConfig;
private final Map<StatefulConnection<?, ?>, GenericObjectPool<StatefulConnection<?, ?>>> poolRef = new ConcurrentHashMap<>(
32);
@@ -97,7 +97,6 @@ class LettucePoolingConnectionProvider implements LettuceConnectionProvider, Red
try {
newPool.preparePool();
} catch (Exception ex) {
throw new PoolException("Could not prepare the pool", ex);
}

View File

@@ -19,10 +19,12 @@ import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import redis.clients.jedis.DefaultJedisClientConfig;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisClientConfig;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.RedisProtocol;
import redis.clients.jedis.util.Pool;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
@@ -265,6 +267,28 @@ class JedisConnectionFactoryUnitTests {
assertThat(connectionFactory.getPoolConfig()).isSameAs(poolConfig);
}
@Test // GH-3072
void shouldInitializePool() throws Exception {
JedisPoolConfig poolConfig = new JedisPoolConfig();
Pool<Jedis> poolMock = mock(Pool.class);
JedisClientConfiguration configuration = JedisClientConfiguration.builder() //
.usePooling().poolConfig(poolConfig) //
.build();
connectionFactory = new JedisConnectionFactory(new RedisStandaloneConfiguration(), configuration) {
@Override
protected Pool<Jedis> createRedisPool() {
return poolMock;
}
};
connectionFactory.afterPropertiesSet();
verify(poolMock).preparePool();
}
@Test // DATAREDIS-574
void shouldReturnStandaloneConfiguration() {
@@ -382,12 +406,12 @@ class JedisConnectionFactoryUnitTests {
private JedisConnectionFactory initSpyedConnectionFactory(RedisSentinelConfiguration sentinelConfiguration,
@Nullable JedisPoolConfig poolConfig) {
Pool<Jedis> poolMock = mock(Pool.class);
// we have to use a spy here as jedis would start connecting to redis sentinels when the pool is created.
JedisConnectionFactory connectionFactorySpy = spy(new JedisConnectionFactory(sentinelConfiguration, poolConfig));
doReturn(null).when(connectionFactorySpy).createRedisSentinelPool(any(RedisSentinelConfiguration.class));
doReturn(null).when(connectionFactorySpy).createRedisPool();
doReturn(poolMock).when(connectionFactorySpy).createRedisSentinelPool(any(RedisSentinelConfiguration.class));
doReturn(poolMock).when(connectionFactorySpy).createRedisPool();
return connectionFactorySpy;
}

View File

@@ -17,6 +17,7 @@ package org.springframework.data.redis.connection.lettuce;
import static org.mockito.Mockito.*;
import io.lettuce.core.api.StatefulConnection;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.async.RedisAsyncCommands;
@@ -74,10 +75,10 @@ class LettucePoolingConnectionProviderUnitTests {
verify(commandsMock).discard();
}
@Test
@Test // GH-3072
void shouldPrepareThePool() {
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
GenericObjectPoolConfig<StatefulConnection<?, ?>> poolConfig = new GenericObjectPoolConfig<>();
poolConfig.setMinIdle(5);
poolConfig.setMaxIdle(8);
poolConfig.setMaxTotal(10);