Skip to content

Commit c517664

Browse files
SOOHYUN-LIMwilkinsona
authored andcommitted
Add a customizer for Lettuce's ClientOptions
See gh-40484
1 parent 4f6860f commit c517664

File tree

3 files changed

+62
-12
lines changed

3 files changed

+62
-12
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright 2012-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.autoconfigure.data.redis;
18+
19+
import io.lettuce.core.ClientOptions;
20+
21+
/**
22+
* Callback interface that can be implemented by beans wishing to customize the
23+
* {@link ClientOptions} through a {@link ClientOptions.Builder} whilst retaining default
24+
* auto-configuration.
25+
*
26+
* @author Soohyun Lim
27+
*/
28+
@FunctionalInterface
29+
public interface LettuceClientOptionsBuilderCustomizer {
30+
31+
/**
32+
* Customize the {@link ClientOptions.Builder}.
33+
* @param clientOptionsBuilder the builder to customize
34+
*/
35+
void customize(ClientOptions.Builder clientOptionsBuilder);
36+
37+
}

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

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -88,29 +88,32 @@ DefaultClientResources lettuceClientResources(ObjectProvider<ClientResourcesBuil
8888
@ConditionalOnMissingBean(RedisConnectionFactory.class)
8989
@ConditionalOnThreading(Threading.PLATFORM)
9090
LettuceConnectionFactory redisConnectionFactory(
91-
ObjectProvider<LettuceClientConfigurationBuilderCustomizer> builderCustomizers,
91+
ObjectProvider<LettuceClientConfigurationBuilderCustomizer> clientConfigurationBuilderCustomizers,
92+
ObjectProvider<LettuceClientOptionsBuilderCustomizer> clientOptionsBuilderCustomizers,
9293
ClientResources clientResources) {
93-
return createConnectionFactory(builderCustomizers, clientResources);
94+
return createConnectionFactory(clientConfigurationBuilderCustomizers, clientOptionsBuilderCustomizers, clientResources);
9495
}
9596

9697
@Bean
9798
@ConditionalOnMissingBean(RedisConnectionFactory.class)
9899
@ConditionalOnThreading(Threading.VIRTUAL)
99100
LettuceConnectionFactory redisConnectionFactoryVirtualThreads(
100-
ObjectProvider<LettuceClientConfigurationBuilderCustomizer> builderCustomizers,
101+
ObjectProvider<LettuceClientConfigurationBuilderCustomizer> clientConfigurationBuilderCustomizers,
102+
ObjectProvider<LettuceClientOptionsBuilderCustomizer> clientOptionsBuilderCustomizers,
101103
ClientResources clientResources) {
102-
LettuceConnectionFactory factory = createConnectionFactory(builderCustomizers, clientResources);
104+
LettuceConnectionFactory factory = createConnectionFactory(clientConfigurationBuilderCustomizers, clientOptionsBuilderCustomizers, clientResources);
103105
SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor("redis-");
104106
executor.setVirtualThreads(true);
105107
factory.setExecutor(executor);
106108
return factory;
107109
}
108110

109111
private LettuceConnectionFactory createConnectionFactory(
110-
ObjectProvider<LettuceClientConfigurationBuilderCustomizer> builderCustomizers,
112+
ObjectProvider<LettuceClientConfigurationBuilderCustomizer> clientConfigurationBuilderCustomizers,
113+
ObjectProvider<LettuceClientOptionsBuilderCustomizer> clientOptionsBuilderCustomizers,
111114
ClientResources clientResources) {
112-
LettuceClientConfiguration clientConfig = getLettuceClientConfiguration(builderCustomizers, clientResources,
113-
getProperties().getLettuce().getPool());
115+
LettuceClientConfiguration clientConfig = getLettuceClientConfiguration(clientConfigurationBuilderCustomizers, clientOptionsBuilderCustomizers,
116+
clientResources, getProperties().getLettuce().getPool());
114117
return createLettuceConnectionFactory(clientConfig);
115118
}
116119

@@ -125,16 +128,17 @@ private LettuceConnectionFactory createLettuceConnectionFactory(LettuceClientCon
125128
}
126129

127130
private LettuceClientConfiguration getLettuceClientConfiguration(
128-
ObjectProvider<LettuceClientConfigurationBuilderCustomizer> builderCustomizers,
131+
ObjectProvider<LettuceClientConfigurationBuilderCustomizer> clientConfigurationBuilderCustomizers,
132+
ObjectProvider<LettuceClientOptionsBuilderCustomizer> clientOptionsBuilderCustomizers,
129133
ClientResources clientResources, Pool pool) {
130134
LettuceClientConfigurationBuilder builder = createBuilder(pool);
131135
applyProperties(builder);
132136
if (StringUtils.hasText(getProperties().getUrl())) {
133137
customizeConfigurationFromUrl(builder);
134138
}
135-
builder.clientOptions(createClientOptions());
139+
builder.clientOptions(createClientOptions(clientOptionsBuilderCustomizers));
136140
builder.clientResources(clientResources);
137-
builderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
141+
clientConfigurationBuilderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
138142
return builder.build();
139143
}
140144

@@ -163,7 +167,7 @@ private void applyProperties(LettuceClientConfiguration.LettuceClientConfigurati
163167
}
164168
}
165169

166-
private ClientOptions createClientOptions() {
170+
private ClientOptions createClientOptions(ObjectProvider<LettuceClientOptionsBuilderCustomizer> clientConfigurationBuilderCustomizers) {
167171
ClientOptions.Builder builder = initializeClientOptionsBuilder();
168172
Duration connectTimeout = getProperties().getConnectTimeout();
169173
if (connectTimeout != null) {
@@ -183,7 +187,9 @@ private ClientOptions createClientOptions() {
183187
}
184188
builder.sslOptions(sslOptionsBuilder.build());
185189
}
186-
return builder.timeoutOptions(TimeoutOptions.enabled()).build();
190+
builder.timeoutOptions(TimeoutOptions.enabled());
191+
clientConfigurationBuilderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
192+
return builder.build();
187193
}
188194

189195
private ClientOptions.Builder initializeClientOptionsBuilder() {

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/redis/RedisAutoConfigurationTests.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ void testCustomizeRedisConfiguration() {
127127
this.contextRunner.withUserConfiguration(CustomConfiguration.class).run((context) -> {
128128
LettuceConnectionFactory cf = context.getBean(LettuceConnectionFactory.class);
129129
assertThat(cf.isUseSsl()).isTrue();
130+
cf.getClientConfiguration().getClientOptions().ifPresent(options ->
131+
assertThat(options.isAutoReconnect()).isFalse());
130132
});
131133
}
132134

@@ -638,6 +640,11 @@ LettuceClientConfigurationBuilderCustomizer customizer() {
638640
return LettuceClientConfigurationBuilder::useSsl;
639641
}
640642

643+
@Bean
644+
LettuceClientOptionsBuilderCustomizer clientOptionsBuilderCustomizer() {
645+
return builder -> builder.autoReconnect(false);
646+
}
647+
641648
}
642649

643650
@Configuration(proxyBeanMethods = false)

0 commit comments

Comments
 (0)