Skip to content

Commit befbf86

Browse files
committed
Support Lettuce static master-replica auto-configuration
Signed-off-by: 용현 <[email protected]>
1 parent b387a08 commit befbf86

File tree

9 files changed

+122
-253
lines changed

9 files changed

+122
-253
lines changed

module/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/autoconfigure/JedisConnectionConfiguration.java

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
import org.springframework.data.redis.connection.RedisConnectionFactory;
3939
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
4040
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
41-
import org.springframework.data.redis.connection.RedisStaticMasterReplicaConfiguration;
4241
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
4342
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration.JedisClientConfigurationBuilder;
4443
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration.JedisSslClientConfigurationBuilder;
@@ -56,7 +55,6 @@
5655
* @author Andy Wilkinson
5756
* @author Phillip Webb
5857
* @author Scott Frederick
59-
* @author Yong-Hyun Kim
6058
*/
6159
@Configuration(proxyBeanMethods = false)
6260
@ConditionalOnClass({ GenericObjectPool.class, JedisConnection.class, Jedis.class })
@@ -66,12 +64,10 @@ class JedisConnectionConfiguration extends RedisConnectionConfiguration {
6664

6765
JedisConnectionConfiguration(RedisProperties properties,
6866
ObjectProvider<RedisStandaloneConfiguration> standaloneConfigurationProvider,
69-
ObjectProvider<RedisSentinelConfiguration> sentinelConfigurationProvider,
70-
ObjectProvider<RedisClusterConfiguration> clusterConfigurationProvider,
71-
ObjectProvider<RedisStaticMasterReplicaConfiguration> staticMasterReplicaConfigurationProvider,
72-
RedisConnectionDetails connectionDetails) {
73-
super(properties, connectionDetails, standaloneConfigurationProvider, sentinelConfigurationProvider,
74-
clusterConfigurationProvider, staticMasterReplicaConfigurationProvider);
67+
ObjectProvider<RedisSentinelConfiguration> sentinelConfiguration,
68+
ObjectProvider<RedisClusterConfiguration> clusterConfiguration, RedisConnectionDetails connectionDetails) {
69+
super(properties, connectionDetails, standaloneConfigurationProvider, sentinelConfiguration,
70+
clusterConfiguration);
7571
}
7672

7773
@Bean
@@ -107,7 +103,6 @@ private JedisConnectionFactory createJedisConnectionFactory(
107103
Assert.state(sentinelConfig != null, "'sentinelConfig' must not be null");
108104
yield new JedisConnectionFactory(sentinelConfig, clientConfiguration);
109105
}
110-
case STATIC_MASTER_REPLICA -> throw new IllegalStateException("Static master-replica mode is not supported by Jedis");
111106
};
112107
}
113108

module/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/autoconfigure/LettuceConnectionConfiguration.java

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
package org.springframework.boot.data.redis.autoconfigure;
1818

1919
import java.time.Duration;
20+
import java.util.Collections;
21+
import java.util.List;
2022

2123
import io.lettuce.core.ClientOptions;
2224
import io.lettuce.core.ReadFrom;
@@ -37,7 +39,9 @@
3739
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
3840
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
3941
import org.springframework.boot.autoconfigure.condition.ConditionalOnThreading;
42+
import org.springframework.boot.data.redis.autoconfigure.RedisConnectionDetails.Node;
4043
import org.springframework.boot.data.redis.autoconfigure.RedisProperties.Lettuce.Cluster.Refresh;
44+
import org.springframework.boot.data.redis.autoconfigure.RedisProperties.Lettuce.StaticMasterReplica;
4145
import org.springframework.boot.data.redis.autoconfigure.RedisProperties.Pool;
4246
import org.springframework.boot.ssl.SslBundle;
4347
import org.springframework.boot.ssl.SslOptions;
@@ -55,6 +59,7 @@
5559
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
5660
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
5761
import org.springframework.util.Assert;
62+
import org.springframework.util.CollectionUtils;
5863
import org.springframework.util.StringUtils;
5964

6065
/**
@@ -76,10 +81,9 @@ class LettuceConnectionConfiguration extends RedisConnectionConfiguration {
7681
ObjectProvider<RedisStandaloneConfiguration> standaloneConfigurationProvider,
7782
ObjectProvider<RedisSentinelConfiguration> sentinelConfigurationProvider,
7883
ObjectProvider<RedisClusterConfiguration> clusterConfigurationProvider,
79-
ObjectProvider<RedisStaticMasterReplicaConfiguration> staticMasterReplicaConfigurationProvider,
8084
RedisConnectionDetails connectionDetails) {
8185
super(properties, connectionDetails, standaloneConfigurationProvider, sentinelConfigurationProvider,
82-
clusterConfigurationProvider, staticMasterReplicaConfigurationProvider);
86+
clusterConfigurationProvider);
8387
}
8488

8589
@Bean(destroyMethod = "shutdown")
@@ -123,6 +127,12 @@ private LettuceConnectionFactory createConnectionFactory(
123127
LettuceClientConfiguration clientConfiguration = getLettuceClientConfiguration(
124128
clientConfigurationBuilderCustomizers, clientOptionsBuilderCustomizers, clientResources,
125129
getProperties().getLettuce().getPool());
130+
131+
RedisStaticMasterReplicaConfiguration staticMasterReplicaConfiguration = getStaticMasterReplicaConfiguration();
132+
if (staticMasterReplicaConfiguration != null) {
133+
return new LettuceConnectionFactory(staticMasterReplicaConfiguration, clientConfiguration);
134+
}
135+
126136
return switch (this.mode) {
127137
case STANDALONE -> new LettuceConnectionFactory(getStandaloneConfig(), clientConfiguration);
128138
case CLUSTER -> {
@@ -135,15 +145,29 @@ private LettuceConnectionFactory createConnectionFactory(
135145
Assert.state(sentinelConfig != null, "'sentinelConfig' must not be null");
136146
yield new LettuceConnectionFactory(sentinelConfig, clientConfiguration);
137147
}
138-
case STATIC_MASTER_REPLICA -> {
139-
RedisStaticMasterReplicaConfiguration staticMasterReplicaConfiguration = getStaticMasterReplicaConfiguration();
140-
Assert.state(staticMasterReplicaConfiguration != null,
141-
"'staticMasterReplicaConfiguration' must not be null");
142-
yield new LettuceConnectionFactory(staticMasterReplicaConfiguration, clientConfiguration);
143-
}
144148
};
145149
}
146150

151+
private @Nullable RedisStaticMasterReplicaConfiguration getStaticMasterReplicaConfiguration() {
152+
StaticMasterReplica staticMasterReplica = getProperties().getLettuce().getStaticMasterReplica();
153+
154+
if (!CollectionUtils.isEmpty(staticMasterReplica.getNodes())) {
155+
List<Node> nodes = asNodes(staticMasterReplica.getNodes());
156+
RedisStaticMasterReplicaConfiguration configuration = new RedisStaticMasterReplicaConfiguration(
157+
nodes.get(0).host(), nodes.get(0).port());
158+
configuration.setUsername(getProperties().getUsername());
159+
if (StringUtils.hasText(getProperties().getPassword())) {
160+
configuration.setPassword(getProperties().getPassword());
161+
}
162+
configuration.setDatabase(getProperties().getDatabase());
163+
nodes.stream().skip(1).forEach((node) -> configuration.addNode(node.host(), node.port()));
164+
165+
return configuration;
166+
}
167+
168+
return null;
169+
}
170+
147171
private LettuceClientConfiguration getLettuceClientConfiguration(
148172
ObjectProvider<LettuceClientConfigurationBuilderCustomizer> clientConfigurationBuilderCustomizers,
149173
ObjectProvider<LettuceClientOptionsBuilderCustomizer> clientOptionsBuilderCustomizers,
@@ -259,6 +283,20 @@ private void customizeConfigurationFromUrl(LettuceClientConfiguration.LettuceCli
259283
}
260284
}
261285

286+
private List<Node> asNodes(@Nullable List<String> nodes) {
287+
if (nodes == null) {
288+
return Collections.emptyList();
289+
}
290+
return nodes.stream().map(this::asNode).toList();
291+
}
292+
293+
private Node asNode(String node) {
294+
int portSeparatorIndex = node.lastIndexOf(':');
295+
String host = node.substring(0, portSeparatorIndex);
296+
int port = Integer.parseInt(node.substring(portSeparatorIndex + 1));
297+
return new Node(host, port);
298+
}
299+
262300
/**
263301
* Inner class to allow optional commons-pool2 dependency.
264302
*/

module/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/autoconfigure/PropertiesRedisConnectionDetails.java

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
* @author Scott Frederick
3636
* @author Yanming Zhou
3737
* @author Phillip Webb
38-
* @author Yong-Hyun Kim
3938
*/
4039
class PropertiesRedisConnectionDetails implements RedisConnectionDetails {
4140

@@ -93,12 +92,6 @@ public Standalone getStandalone() {
9392
return (cluster != null) ? new PropertiesCluster(cluster) : null;
9493
}
9594

96-
@Override
97-
public @Nullable StaticMasterReplica getStaticMasterReplica() {
98-
RedisProperties.StaticMasterReplica staticMasterReplica = this.properties.getStaticMasterReplica();
99-
return (staticMasterReplica != null) ? new PropertiesStaticMasterReplica(getStandalone().getDatabase(), staticMasterReplica) : null;
100-
}
101-
10295
private @Nullable RedisUrl getRedisUrl() {
10396
return RedisUrl.of(this.properties.getUrl());
10497
}
@@ -188,35 +181,4 @@ public List<Node> getNodes() {
188181

189182
}
190183

191-
/**
192-
* {@link StaticMasterReplica} implementation backed by properties.
193-
*/
194-
private class PropertiesStaticMasterReplica implements StaticMasterReplica {
195-
196-
private final int database;
197-
198-
private final RedisProperties.StaticMasterReplica properties;
199-
200-
PropertiesStaticMasterReplica(int database, RedisProperties.StaticMasterReplica properties) {
201-
this.database = database;
202-
this.properties = properties;
203-
}
204-
205-
@Override
206-
public int getDatabase() {
207-
return this.database;
208-
}
209-
210-
@Override
211-
public List<Node> getNodes() {
212-
return asNodes(this.properties.getNodes());
213-
}
214-
215-
@Override
216-
public @Nullable SslBundle getSslBundle() {
217-
return PropertiesRedisConnectionDetails.this.getSslBundle();
218-
}
219-
220-
}
221-
222184
}

module/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/autoconfigure/RedisConnectionConfiguration.java

Lines changed: 2 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
import org.springframework.data.redis.connection.RedisPassword;
3434
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
3535
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
36-
import org.springframework.data.redis.connection.RedisStaticMasterReplicaConfiguration;
3736
import org.springframework.util.Assert;
3837
import org.springframework.util.ClassUtils;
3938

@@ -49,7 +48,6 @@
4948
* @author Andy Wilkinson
5049
* @author Phillip Webb
5150
* @author Yanming Zhou
52-
* @author Yong-Hyun Kim
5351
*/
5452
abstract class RedisConnectionConfiguration {
5553

@@ -64,23 +62,19 @@ abstract class RedisConnectionConfiguration {
6462

6563
private final @Nullable RedisClusterConfiguration clusterConfiguration;
6664

67-
private final @Nullable RedisStaticMasterReplicaConfiguration staticMasterReplicaConfiguration;
68-
6965
private final RedisConnectionDetails connectionDetails;
7066

7167
protected final Mode mode;
7268

7369
protected RedisConnectionConfiguration(RedisProperties properties, RedisConnectionDetails connectionDetails,
7470
ObjectProvider<RedisStandaloneConfiguration> standaloneConfigurationProvider,
7571
ObjectProvider<RedisSentinelConfiguration> sentinelConfigurationProvider,
76-
ObjectProvider<RedisClusterConfiguration> clusterConfigurationProvider,
77-
ObjectProvider<RedisStaticMasterReplicaConfiguration> staticMasterReplicaConfigurationProvider) {
72+
ObjectProvider<RedisClusterConfiguration> clusterConfigurationProvider) {
7873
this.properties = properties;
7974
this.standaloneConfiguration = standaloneConfigurationProvider.getIfAvailable();
8075
this.sentinelConfiguration = sentinelConfigurationProvider.getIfAvailable();
8176
this.clusterConfiguration = clusterConfigurationProvider.getIfAvailable();
8277
this.connectionDetails = connectionDetails;
83-
this.staticMasterReplicaConfiguration = staticMasterReplicaConfigurationProvider.getIfAvailable();
8478
this.mode = determineMode();
8579
}
8680

@@ -148,31 +142,6 @@ protected final RedisStandaloneConfiguration getStandaloneConfig() {
148142
return null;
149143
}
150144

151-
/**
152-
* Create a {@link RedisStaticMasterReplicaConfiguration} if necessary.
153-
* @return {@literal null} if no static master-replica settings are set.
154-
*/
155-
protected final @Nullable RedisStaticMasterReplicaConfiguration getStaticMasterReplicaConfiguration() {
156-
if (this.staticMasterReplicaConfiguration != null) {
157-
return this.staticMasterReplicaConfiguration;
158-
}
159-
if (this.connectionDetails.getStaticMasterReplica() != null) {
160-
List<Node> nodes = this.connectionDetails.getStaticMasterReplica().getNodes();
161-
Assert.notEmpty(nodes, "'staticMasterReplica.nodes' must not be empty'");
162-
Node firstNode = nodes.get(0);
163-
RedisStaticMasterReplicaConfiguration config = new RedisStaticMasterReplicaConfiguration(firstNode.host(), firstNode.port());
164-
nodes.stream().skip(1).forEach(node -> config.addNode(node.host(), node.port()));
165-
config.setUsername(this.connectionDetails.getUsername());
166-
String password = this.connectionDetails.getPassword();
167-
if (password != null) {
168-
config.setPassword(RedisPassword.of(password));
169-
}
170-
config.setDatabase(this.connectionDetails.getStaticMasterReplica().getDatabase());
171-
return config;
172-
}
173-
return null;
174-
}
175-
176145
private List<RedisNode> getNodes(Cluster cluster) {
177146
return cluster.getNodes().stream().map(this::asRedisNode).toList();
178147
}
@@ -193,8 +162,6 @@ protected final RedisProperties getProperties() {
193162
? this.connectionDetails.getCluster().getSslBundle() : null;
194163
case SENTINEL -> (this.connectionDetails.getSentinel() != null)
195164
? this.connectionDetails.getSentinel().getSslBundle() : null;
196-
case STATIC_MASTER_REPLICA -> (this.connectionDetails.getStaticMasterReplica() != null)
197-
? this.connectionDetails.getStaticMasterReplica().getSslBundle() : null;
198165
};
199166
}
200167

@@ -230,15 +197,12 @@ private Mode determineMode() {
230197
if (getClusterConfiguration() != null) {
231198
return Mode.CLUSTER;
232199
}
233-
if (getStaticMasterReplicaConfiguration() != null) {
234-
return Mode.STATIC_MASTER_REPLICA;
235-
}
236200
return Mode.STANDALONE;
237201
}
238202

239203
enum Mode {
240204

241-
STANDALONE, CLUSTER, SENTINEL, STATIC_MASTER_REPLICA
205+
STANDALONE, CLUSTER, SENTINEL
242206

243207
}
244208

0 commit comments

Comments
 (0)