createRedisPool() {
- return new JedisPool(getPoolConfig(), new HostAndPort(getHostName(), getPort()), this.clientConfig);
+ return new JedisPool(getPoolConfig(), newHostAndPort(getHostName(), getPort()), this.clientConfig);
}
/**
- * Template method to create a {@link ClusterTopologyProvider} given {@link JedisCluster}. Creates
- * {@link JedisClusterTopologyProvider} by default.
- *
- * @param cluster the {@link JedisCluster}, must not be {@literal null}.
- * @return the {@link ClusterTopologyProvider}.
- * @see JedisClusterTopologyProvider
- * @see 2.2
+ * @deprecated Use {@link #createClusterTopologyProvider(JedisCluster)} instead.
+ * @since 2.2
*/
+ @Deprecated(since = "3.2")
protected ClusterTopologyProvider createTopologyProvider(JedisCluster cluster) {
return new JedisClusterTopologyProvider(cluster);
}
+ /**
+ * Template method to create a {@link ClusterTopologyProvider} with the given {@link JedisCluster}.
+ *
+ * Creates {@link JedisClusterTopologyProvider} by default.
+ *
+ * @param cluster reference to the configured {@link JedisCluster} used by the {@link ClusterTopologyProvider}
+ * to interact with the Redis cluster; must not be {@literal null}.
+ * @return a new {@link ClusterTopologyProvider}.
+ * @since 3.2
+ */
+ protected ClusterTopologyProvider createClusterTopologyProvider(JedisCluster cluster) {
+ return createTopologyProvider(cluster);
+ }
+
+ /**
+ * Create a new {@link ClusterCommandExecutor} with the given {@link JedisCluster} and {@link ClusterTopologyProvider}.
+ *
+ * Creates a {@link JedisClusterNodeResourceProvider} by default.
+ *
+ * @param cluster reference to the configured {@link JedisCluster} and {@link ClusterTopologyProvider} used to
+ * execute Redis commands across the cluster; must not be {@literal null}.
+ * @param clusterTopologyProvider {@link ClusterTopologyProvider} used to gather information about the current
+ * Redis cluster topology.
+ * @return a new {@link ClusterCommandExecutor}.
+ * @since 3.2
+ */
+ protected ClusterCommandExecutor createClusterCommandExecutor(JedisCluster cluster,
+ ClusterTopologyProvider clusterTopologyProvider) {
+
+ JedisClusterNodeResourceProvider clusterNodeResourceProvider =
+ new JedisClusterNodeResourceProvider(cluster, clusterTopologyProvider);
+
+ return new ClusterCommandExecutor(clusterTopologyProvider, clusterNodeResourceProvider, EXCEPTION_TRANSLATION,
+ this.asyncExecutor);
+ }
+
/**
* Creates {@link JedisCluster} for given {@link RedisClusterConfiguration} and {@link GenericObjectPoolConfig}.
*
@@ -841,8 +875,9 @@ public RedisConnection getConnection() {
sentinelConfig = createSentinelClientConfig(sentinelConfiguration);
}
- JedisConnection connection = getUsePool() ? new JedisConnection(jedis, this.pool, this.clientConfig, sentinelConfig)
- : new JedisConnection(jedis, null, this.clientConfig, sentinelConfig);
+ Pool pool = getUsePool() ? this.pool : null;
+
+ JedisConnection connection = new JedisConnection(jedis, pool, this.clientConfig, sentinelConfig);
connection.setConvertPipelineAndTxResults(convertPipelineAndTxResults);
@@ -863,19 +898,16 @@ protected Jedis fetchJedisConnector() {
return this.pool.getResource();
}
- Jedis jedis = createJedis();
+ Jedis jedis = createJedis(getHostName(), getPort(), this.clientConfig);
// force initialization (see Jedis issue #82)
jedis.connect();
return jedis;
- } catch (Exception cause) {
- throw new RedisConnectionFailureException("Cannot get Jedis connection", cause);
- }
- }
- private Jedis createJedis() {
- return new Jedis(new HostAndPort(getHostName(), getPort()), this.clientConfig);
+ } catch (Exception e) {
+ throw new RedisConnectionFailureException("Cannot get Jedis connection", e);
+ }
}
/**
@@ -935,10 +967,13 @@ public RedisSentinelConnection getSentinelConnection() {
private Jedis getActiveSentinel() {
- Assert.isTrue(RedisConfiguration.isSentinelConfiguration(configuration), "SentinelConfig must not be null");
- SentinelConfiguration sentinelConfiguration = (SentinelConfiguration) configuration;
+ Assert.isTrue(RedisConfiguration.isSentinelConfiguration(this.configuration),
+ "SentinelConfig must not be null");
+
+ SentinelConfiguration sentinelConfiguration = (SentinelConfiguration) this.configuration;
JedisClientConfig clientConfig = createSentinelClientConfig(sentinelConfiguration);
+
for (RedisNode node : sentinelConfiguration.getSentinels()) {
Jedis jedis = null;
@@ -946,13 +981,14 @@ private Jedis getActiveSentinel() {
try {
- jedis = new Jedis(new HostAndPort(node.getHost(), node.getPort()), clientConfig);
+ jedis = createJedis(node, clientConfig);
+
if (jedis.ping().equalsIgnoreCase("pong")) {
success = true;
return jedis;
}
- } catch (Exception ex) {
- log.warn(String.format("Ping failed for sentinel host: %s", node.getHost()), ex);
+ } catch (Exception e) {
+ log.warn("Ping failed for sentinel host: %s".formatted(node.getHost()), e);
} finally {
if (!success && jedis != null) {
jedis.close();
@@ -963,6 +999,30 @@ private Jedis getActiveSentinel() {
throw new InvalidDataAccessResourceUsageException("No Sentinel found");
}
+ private boolean isCreatedOrStopped(@Nullable State state) {
+ return State.CREATED.equals(state) || State.STOPPED.equals(state);
+ }
+
+ private boolean isStarted(@Nullable State state) {
+ return State.STARTED.equals(state);
+ }
+
+ private Jedis createJedis(String hostname, int port, JedisClientConfig config) {
+ return createJedis(newHostAndPort(hostname, port), config);
+ }
+
+ private Jedis createJedis(RedisNode node, JedisClientConfig config) {
+ return createJedis(newHostAndPort(node), config);
+ }
+
+ private Jedis createJedis(HostAndPort hostPort, JedisClientConfig config) {
+ return new Jedis(hostPort, config);
+ }
+
+ private Pool createPool() {
+ return isRedisSentinelAware() ? createRedisSentinelPool(getSentinelConfiguration()) : createRedisPool();
+ }
+
private static Set convertToJedisSentinelSet(Collection nodes) {
if (CollectionUtils.isEmpty(nodes)) {
@@ -970,53 +1030,81 @@ private static Set convertToJedisSentinelSet(Collection
}
Set convertedNodes = new LinkedHashSet<>(nodes.size());
+
for (RedisNode node : nodes) {
if (node != null) {
- convertedNodes.add(new HostAndPort(node.getHost(), node.getPort()));
+ convertedNodes.add(newHostAndPort(node));
}
}
+
return convertedNodes;
}
- private int getReadTimeout() {
- return Math.toIntExact(clientConfiguration.getReadTimeout().toMillis());
+ private static HostAndPort newHostAndPort(String hostname, int port) {
+ return new HostAndPort(hostname, port);
+ }
+
+ private static HostAndPort newHostAndPort(RedisNode node) {
+ return new HostAndPort(node.getHost(), node.getPort());
+ }
+
+ private GenericObjectPoolConfig nullSafePoolConfig(@Nullable GenericObjectPoolConfig poolConfig) {
+ return poolConfig != null ? poolConfig : new JedisPoolConfig();
}
private int getConnectTimeout() {
return Math.toIntExact(clientConfiguration.getConnectTimeout().toMillis());
}
+ private int getReadTimeout() {
+ return Math.toIntExact(clientConfiguration.getReadTimeout().toMillis());
+ }
+
+ @Nullable
+ private String getRedisUsername() {
+ return RedisConfiguration.getUsernameOrElse(this.configuration, standaloneConfig::getUsername);
+ }
+
+ private RedisPassword getRedisPassword() {
+ return RedisConfiguration.getPasswordOrElse(this.configuration, standaloneConfig::getPassword);
+ }
+
private MutableJedisClientConfiguration getMutableConfiguration() {
Assert.state(clientConfiguration instanceof MutableJedisClientConfiguration,
- () -> String.format("Client configuration must be instance of MutableJedisClientConfiguration but is %s",
- ClassUtils.getShortName(clientConfiguration.getClass())));
+ () -> "Client configuration must be instance of MutableJedisClientConfiguration but is %s"
+ .formatted(ClassUtils.getShortName(clientConfiguration.getClass())));
return (MutableJedisClientConfiguration) clientConfiguration;
}
private void assertInitialized() {
- State current = state.get();
+ State state = this.state.get();
- if (State.STARTED.equals(current)) {
+ if (isStarted(state)) {
return;
}
- switch (current) {
- case CREATED, STOPPED -> throw new IllegalStateException(
- String.format("JedisConnectionFactory has been %s. Use start() to initialize it", current));
- case DESTROYED -> throw new IllegalStateException(
- "JedisConnectionFactory was destroyed and cannot be used anymore");
- default -> throw new IllegalStateException(String.format("JedisConnectionFactory is %s", current));
+ switch (state) {
+ case CREATED, STOPPED ->
+ throwIllegalStateException("JedisConnectionFactory has been %s. Call start() to initialize", state);
+ case DESTROYED ->
+ throwIllegalStateException("JedisConnectionFactory was destroyed and cannot be used anymore");
+ default -> throwIllegalStateException("JedisConnectionFactory is %s", state);
}
}
+ private void throwIllegalStateException(String message, Object... args) {
+ throw new IllegalStateException(message.formatted(args));
+ }
+
/**
* Mutable implementation of {@link JedisClientConfiguration}.
*
* @author Mark Paluch
*/
+ @SuppressWarnings("rawtypes")
static class MutableJedisClientConfiguration implements JedisClientConfiguration {
private boolean useSsl;
@@ -1032,7 +1120,9 @@ static class MutableJedisClientConfiguration implements JedisClientConfiguration
public static JedisClientConfiguration create(GenericObjectPoolConfig jedisPoolConfig) {
MutableJedisClientConfiguration configuration = new MutableJedisClientConfiguration();
+
configuration.setPoolConfig(jedisPoolConfig);
+
return configuration;
}