1717package org .springframework .boot .data .redis .autoconfigure ;
1818
1919import java .time .Duration ;
20+ import java .util .Collections ;
21+ import java .util .List ;
2022
2123import io .lettuce .core .ClientOptions ;
2224import io .lettuce .core .ReadFrom ;
3739import org .springframework .boot .autoconfigure .condition .ConditionalOnMissingBean ;
3840import org .springframework .boot .autoconfigure .condition .ConditionalOnProperty ;
3941import org .springframework .boot .autoconfigure .condition .ConditionalOnThreading ;
42+ import org .springframework .boot .data .redis .autoconfigure .RedisConnectionDetails .Node ;
4043import org .springframework .boot .data .redis .autoconfigure .RedisProperties .Lettuce .Cluster .Refresh ;
44+ import org .springframework .boot .data .redis .autoconfigure .RedisProperties .Lettuce .StaticMasterReplica ;
4145import org .springframework .boot .data .redis .autoconfigure .RedisProperties .Pool ;
4246import org .springframework .boot .ssl .SslBundle ;
4347import org .springframework .boot .ssl .SslOptions ;
5559import org .springframework .data .redis .connection .lettuce .LettuceConnectionFactory ;
5660import org .springframework .data .redis .connection .lettuce .LettucePoolingClientConfiguration ;
5761import org .springframework .util .Assert ;
62+ import org .springframework .util .CollectionUtils ;
5863import 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 */
0 commit comments