Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.boot.autoconfigure.data.redis;

import io.lettuce.core.ClientOptions;

/**
* Callback interface that can be implemented by beans wishing to customize the
* {@link ClientOptions} through a {@link ClientOptions.Builder} whilst retaining default
* auto-configuration.
*
* @author Soohyun Lim
*/
@FunctionalInterface
public interface LettuceClientOptionsBuilderCustomizer {

/**
* Customize the {@link ClientOptions.Builder}.
* @param clientOptionsBuilder the builder to customize
*/
void customize(ClientOptions.Builder clientOptionsBuilder);

}
Original file line number Diff line number Diff line change
Expand Up @@ -88,29 +88,32 @@ DefaultClientResources lettuceClientResources(ObjectProvider<ClientResourcesBuil
@ConditionalOnMissingBean(RedisConnectionFactory.class)
@ConditionalOnThreading(Threading.PLATFORM)
LettuceConnectionFactory redisConnectionFactory(
ObjectProvider<LettuceClientConfigurationBuilderCustomizer> builderCustomizers,
ObjectProvider<LettuceClientConfigurationBuilderCustomizer> clientConfigurationBuilderCustomizers,
ObjectProvider<LettuceClientOptionsBuilderCustomizer> clientOptionsBuilderCustomizers,
ClientResources clientResources) {
return createConnectionFactory(builderCustomizers, clientResources);
return createConnectionFactory(clientConfigurationBuilderCustomizers, clientOptionsBuilderCustomizers, clientResources);
}

@Bean
@ConditionalOnMissingBean(RedisConnectionFactory.class)
@ConditionalOnThreading(Threading.VIRTUAL)
LettuceConnectionFactory redisConnectionFactoryVirtualThreads(
ObjectProvider<LettuceClientConfigurationBuilderCustomizer> builderCustomizers,
ObjectProvider<LettuceClientConfigurationBuilderCustomizer> clientConfigurationBuilderCustomizers,
ObjectProvider<LettuceClientOptionsBuilderCustomizer> clientOptionsBuilderCustomizers,
ClientResources clientResources) {
LettuceConnectionFactory factory = createConnectionFactory(builderCustomizers, clientResources);
LettuceConnectionFactory factory = createConnectionFactory(clientConfigurationBuilderCustomizers, clientOptionsBuilderCustomizers, clientResources);
SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor("redis-");
executor.setVirtualThreads(true);
factory.setExecutor(executor);
return factory;
}

private LettuceConnectionFactory createConnectionFactory(
ObjectProvider<LettuceClientConfigurationBuilderCustomizer> builderCustomizers,
ObjectProvider<LettuceClientConfigurationBuilderCustomizer> clientConfigurationBuilderCustomizers,
ObjectProvider<LettuceClientOptionsBuilderCustomizer> clientOptionsBuilderCustomizers,
ClientResources clientResources) {
LettuceClientConfiguration clientConfig = getLettuceClientConfiguration(builderCustomizers, clientResources,
getProperties().getLettuce().getPool());
LettuceClientConfiguration clientConfig = getLettuceClientConfiguration(clientConfigurationBuilderCustomizers, clientOptionsBuilderCustomizers,
clientResources, getProperties().getLettuce().getPool());
return createLettuceConnectionFactory(clientConfig);
}

Expand All @@ -125,16 +128,17 @@ private LettuceConnectionFactory createLettuceConnectionFactory(LettuceClientCon
}

private LettuceClientConfiguration getLettuceClientConfiguration(
ObjectProvider<LettuceClientConfigurationBuilderCustomizer> builderCustomizers,
ObjectProvider<LettuceClientConfigurationBuilderCustomizer> clientConfigurationBuilderCustomizers,
ObjectProvider<LettuceClientOptionsBuilderCustomizer> clientOptionsBuilderCustomizers,
ClientResources clientResources, Pool pool) {
LettuceClientConfigurationBuilder builder = createBuilder(pool);
applyProperties(builder);
if (StringUtils.hasText(getProperties().getUrl())) {
customizeConfigurationFromUrl(builder);
}
builder.clientOptions(createClientOptions());
builder.clientOptions(createClientOptions(clientOptionsBuilderCustomizers));
builder.clientResources(clientResources);
builderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
clientConfigurationBuilderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
return builder.build();
}

Expand Down Expand Up @@ -163,7 +167,7 @@ private void applyProperties(LettuceClientConfiguration.LettuceClientConfigurati
}
}

private ClientOptions createClientOptions() {
private ClientOptions createClientOptions(ObjectProvider<LettuceClientOptionsBuilderCustomizer> clientConfigurationBuilderCustomizers) {
ClientOptions.Builder builder = initializeClientOptionsBuilder();
Duration connectTimeout = getProperties().getConnectTimeout();
if (connectTimeout != null) {
Expand All @@ -183,7 +187,9 @@ private ClientOptions createClientOptions() {
}
builder.sslOptions(sslOptionsBuilder.build());
}
return builder.timeoutOptions(TimeoutOptions.enabled()).build();
builder.timeoutOptions(TimeoutOptions.enabled());
clientConfigurationBuilderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
return builder.build();
}

private ClientOptions.Builder initializeClientOptionsBuilder() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ void testCustomizeRedisConfiguration() {
this.contextRunner.withUserConfiguration(CustomConfiguration.class).run((context) -> {
LettuceConnectionFactory cf = context.getBean(LettuceConnectionFactory.class);
assertThat(cf.isUseSsl()).isTrue();
cf.getClientConfiguration().getClientOptions().ifPresent(options ->
assertThat(options.isAutoReconnect()).isFalse());
});
}

Expand Down Expand Up @@ -633,6 +635,11 @@ LettuceClientConfigurationBuilderCustomizer customizer() {
return LettuceClientConfigurationBuilder::useSsl;
}

@Bean
LettuceClientOptionsBuilderCustomizer clientOptionsBuilderCustomizer() {
return builder -> builder.autoReconnect(false);
}

}

@Configuration(proxyBeanMethods = false)
Expand Down