@ -17,6 +17,9 @@
package org.springframework.boot.autoconfigure.data.redis ;
import java.net.UnknownHostException ;
import java.time.Duration ;
import java.util.Collections ;
import java.util.List ;
import io.lettuce.core.RedisClient ;
import io.lettuce.core.cluster.RedisClusterClient ;
@ -33,7 +36,10 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration ;
import org.springframework.data.redis.connection.RedisConnectionFactory ;
import org.springframework.data.redis.connection.RedisSentinelConfiguration ;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration ;
import org.springframework.data.redis.connection.lettuce.DefaultLettucePool ;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration ;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration.LettuceClientConfigurationBuilder ;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory ;
import org.springframework.util.StringUtils ;
@ -49,11 +55,18 @@ class LettuceConnectionConfiguration extends RedisConnectionConfiguration {
private final RedisProperties properties ;
private final List < LettuceClientConfigurationBuilderCustomizer > builderCustomizers ;
LettuceConnectionConfiguration ( RedisProperties properties ,
ObjectProvider < RedisStandaloneConfiguration > standaloneConfiguration ,
ObjectProvider < RedisSentinelConfiguration > sentinelConfigurationProvider ,
ObjectProvider < RedisClusterConfiguration > clusterConfigurationProvider ) {
super ( properties , sentinelConfigurationProvider , clusterConfigurationProvider ) ;
ObjectProvider < RedisClusterConfiguration > clusterConfigurationProvider ,
ObjectProvider < List < LettuceClientConfigurationBuilderCustomizer > > builderCustomizers ) {
super ( properties , standaloneConfiguration , sentinelConfigurationProvider ,
clusterConfigurationProvider ) ;
this . properties = properties ;
this . builderCustomizers = builderCustomizers
. getIfAvailable ( Collections : : emptyList ) ;
}
@Bean ( destroyMethod = "shutdown" )
@ -66,52 +79,26 @@ class LettuceConnectionConfiguration extends RedisConnectionConfiguration {
@ConditionalOnMissingBean ( RedisConnectionFactory . class )
public LettuceConnectionFactory redisConnectionFactory (
ClientResources clientResources ) throws UnknownHostException {
return applyProperties ( createLettuceConnectionFactory ( clientResources ) ) ;
}
private LettuceConnectionFactory applyProperties ( LettuceConnectionFactory factory ) {
configureConnection ( factory ) ;
if ( this . properties . isSsl ( ) ) {
factory . setUseSsl ( true ) ;
}
if ( this . properties . getLettuce ( ) ! = null ) {
RedisProperties . Lettuce lettuce = this . properties . getLettuce ( ) ;
if ( lettuce . getShutdownTimeout ( ) > = 0 ) {
factory . setShutdownTimeout (
this . properties . getLettuce ( ) . getShutdownTimeout ( ) ) ;
}
if ( this . properties . getLettuce ( ) . getPool ( ) ! = null ) {
return createLettuceConnectionFactory ( clientResources ) ;
}
return factory ;
return createLettuceConnectionFactory (
getLettuceClientConfiguration ( clientResources ) ) ;
}
private void configureConnection ( LettuceConnectionFactory factory ) {
if ( StringUtils . hasText ( this . properties . getUrl ( ) ) ) {
configureConnectionFromUrl ( factory ) ;
}
else {
factory . setHostName ( this . properties . getHost ( ) ) ;
factory . setPort ( this . properties . getPort ( ) ) ;
if ( this . properties . getPassword ( ) ! = null ) {
factory . setPassword ( this . properties . getPassword ( ) ) ;
}
factory . setDatabase ( this . properties . getDatabase ( ) ) ;
if ( this . properties . getTimeout ( ) > 0 ) {
factory . setTimeout ( this . properties . getTimeout ( ) ) ;
}
}
private LettuceConnectionFactory createLettuceConnectionFactory (
ClientResources clientResources ) {
return new LettuceConnectionFactory ( applyProperties ( createLettucePool ( ) ,
this . properties . getLettuce ( ) . getPool ( ) , clientResources ) ) ;
}
private void configureConnectionFromUrl ( LettuceConnectionFactory factory ) {
ConnectionInfo connectionInfo = parseUrl ( this . properties . getUrl ( ) ) ;
factory . setUseSsl ( connectionInfo . isUseSsl ( ) ) ;
factory . setHostName ( connectionInfo . getHostName ( ) ) ;
factory . setPort ( connectionInfo . getPort ( ) ) ;
if ( connectionInfo . getPassword ( ) ! = null ) {
factory . setPassword ( connectionInfo . getPassword ( ) ) ;
}
private DefaultLettucePool createLettucePool ( ) {
return getSentinelConfig ( ) ! = null ? new DefaultLettucePool ( getSentinelConfig ( ) )
: new DefaultLettucePool ( ) ;
}
private DefaultLettucePool applyProperties ( DefaultLettucePool pool ) {
private DefaultLettucePool applyProperties ( DefaultLettucePool pool ,
RedisProperties . Pool properties , ClientResources clientResources ) {
if ( StringUtils . hasText ( this . properties . getUrl ( ) ) ) {
configureConnectionFromUrl ( pool ) ;
}
@ -126,6 +113,8 @@ class LettuceConnectionConfiguration extends RedisConnectionConfiguration {
if ( this . properties . getTimeout ( ) > 0 ) {
pool . setTimeout ( this . properties . getTimeout ( ) ) ;
}
pool . setPoolConfig ( lettucePoolConfig ( properties ) ) ;
pool . setClientResources ( clientResources ) ;
pool . afterPropertiesSet ( ) ;
return pool ;
}
@ -139,59 +128,73 @@ class LettuceConnectionConfiguration extends RedisConnectionConfiguration {
}
}
private static GenericObjectPoolConfig lettucePoolConfig ( RedisProperties . Pool props ) {
GenericObjectPoolConfig config = new GenericObjectPoolConfig ( ) ;
config . setMaxTotal ( props . getMaxActive ( ) ) ;
config . setMaxIdle ( props . getMaxIdle ( ) ) ;
config . setMinIdle ( props . getMinIdle ( ) ) ;
config . setMaxWaitMillis ( props . getMaxWait ( ) ) ;
return config ;
}
private LettuceConnectionFactory createLettuceConnectionFactory (
ClientResources clientResources ) {
LettuceClientConfiguration clientConfiguration ) {
if ( getSentinelConfig ( ) ! = null ) {
if ( this . properties . getLettuce ( ) ! = null
& & this . properties . getLettuce ( ) . getPool ( ) ! = null ) {
DefaultLettucePool lettucePool = new DefaultLettucePool (
getSentinelConfig ( ) ) ;
return new LettuceConnectionFactory ( applyProperties (
applyClientResources ( lettucePool , clientResources ) ) ) ;
}
return applyClientResources ( new LettuceConnectionFactory ( getSentinelConfig ( ) ) ,
clientResources ) ;
return new LettuceConnectionFactory ( getSentinelConfig ( ) , clientConfiguration ) ;
}
if ( getClusterConfiguration ( ) ! = null ) {
return applyClientResources (
new LettuceConnectionFactory ( getClusterConfiguration ( ) ) ,
clientResources ) ;
return new LettuceConnectionFactory ( getClusterConfiguration ( ) ,
clientConfiguration ) ;
}
if ( this . properties . getLettuce ( ) ! = null
& & this . properties . getLettuce ( ) . getPool ( ) ! = null ) {
GenericObjectPoolConfig config = lettucePoolConfig (
this . properties . getLettuce ( ) . getPool ( ) ) ;
DefaultLettucePool lettucePool = new DefaultLettucePool (
this . properties . getHost ( ) , this . properties . getPort ( ) , config ) ;
return new LettuceConnectionFactory (
applyProperties ( applyClientResources ( lettucePool , clientResources ) ) ) ;
}
return applyClientResources ( new LettuceConnectionFactory ( ) , clientResources ) ;
return new LettuceConnectionFactory ( getStandaloneConfig ( ) , clientConfiguration ) ;
}
private DefaultLettucePool applyClientResources ( DefaultLettucePool lettucePool ,
private LettuceClientConfiguration getLettuceClientConfiguration (
ClientResources clientResources ) {
lettucePool . setClientResources ( clientResources ) ;
return lettucePool ;
LettuceClientConfigurationBuilder builder = applyProperties (
LettuceClientConfiguration . builder ( ) ) ;
if ( StringUtils . hasText ( this . properties . getUrl ( ) ) ) {
customizeConfigurationFromUrl ( builder ) ;
}
builder . clientResources ( clientResources ) ;
customize ( builder ) ;
return builder . build ( ) ;
}
private LettuceConnectionFactory applyClientResources (
LettuceConnectionFactory factory , ClientResources clientResources ) {
factory . setClientResources ( clientResources ) ;
return factory ;
private LettuceClientConfigurationBuilder applyProperties (
LettuceClientConfiguration . LettuceClientConfigurationBuilder builder ) {
if ( this . properties . isSsl ( ) ) {
builder . useSsl ( ) ;
}
if ( this . properties . getTimeout ( ) ! = 0 ) {
builder . commandTimeout ( Duration . ofMillis ( this . properties . getTimeout ( ) ) ) ;
}
if ( this . properties . getLettuce ( ) ! = null ) {
RedisProperties . Lettuce lettuce = this . properties . getLettuce ( ) ;
if ( lettuce . getShutdownTimeout ( ) > = 0 ) {
builder . shutdownTimeout ( Duration
. ofSeconds ( this . properties . getLettuce ( ) . getShutdownTimeout ( ) ) ) ;
}
}
return builder ;
}
private GenericObjectPoolConfig lettucePoolConfig ( RedisProperties . Pool props ) {
GenericObjectPoolConfig config = new GenericObjectPoolConfig ( ) ;
config . setMaxTotal ( props . getMaxActive ( ) ) ;
config . setMaxIdle ( props . getMaxIdle ( ) ) ;
config . setMinIdle ( props . getMinIdle ( ) ) ;
config . setMaxWaitMillis ( props . getMaxWait ( ) ) ;
return config ;
private void customizeConfigurationFromUrl (
LettuceClientConfiguration . LettuceClientConfigurationBuilder builder ) {
ConnectionInfo connectionInfo = parseUrl ( this . properties . getUrl ( ) ) ;
if ( connectionInfo . isUseSsl ( ) ) {
builder . useSsl ( ) ;
}
}
private void customize (
LettuceClientConfiguration . LettuceClientConfigurationBuilder builder ) {
for ( LettuceClientConfigurationBuilderCustomizer customizer : this . builderCustomizers ) {
customizer . customize ( builder ) ;
}
}
}