Skip to content

Add factory method to LettuceConnectionFactory to create RedisConfiguration from RedisURI #2117

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 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
Expand Up @@ -15,7 +15,16 @@
*/
package org.springframework.data.redis.connection.lettuce;

import static org.springframework.data.redis.connection.lettuce.LettuceConnection.*;
import java.nio.ByteBuffer;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import io.lettuce.core.AbstractRedisClient;
import io.lettuce.core.ClientOptions;
Expand All @@ -30,18 +39,6 @@
import io.lettuce.core.cluster.api.StatefulRedisClusterConnection;
import io.lettuce.core.codec.RedisCodec;
import io.lettuce.core.resource.ClientResources;

import java.nio.ByteBuffer;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

Expand All @@ -52,17 +49,37 @@
import org.springframework.data.redis.ExceptionTranslationStrategy;
import org.springframework.data.redis.PassThroughExceptionTranslationStrategy;
import org.springframework.data.redis.RedisConnectionFailureException;
import org.springframework.data.redis.connection.*;
import org.springframework.data.redis.connection.ClusterCommandExecutor;
import org.springframework.data.redis.connection.ClusterTopologyProvider;
import org.springframework.data.redis.connection.Pool;
import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisClusterConnection;
import org.springframework.data.redis.connection.RedisConfiguration;
import org.springframework.data.redis.connection.RedisConfiguration.ClusterConfiguration;
import org.springframework.data.redis.connection.RedisConfiguration.DomainSocketConfiguration;
import org.springframework.data.redis.connection.RedisConfiguration.WithDatabaseIndex;
import org.springframework.data.redis.connection.RedisConfiguration.WithPassword;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.RedisSentinelConnection;
import org.springframework.data.redis.connection.RedisSocketConfiguration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.RedisStaticMasterReplicaConfiguration;
import org.springframework.data.util.Optionals;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import static org.springframework.data.redis.connection.lettuce.LettuceConnection.CODEC;
import static org.springframework.data.redis.connection.lettuce.LettuceConnection.LettucePoolConnectionProvider;
import static org.springframework.data.redis.connection.lettuce.LettuceConnection.PipeliningFlushPolicy;

/**
* Connection factory creating <a href="https://github.com/mp911de/lettuce">Lettuce</a>-based connections.
* <p>
Expand Down Expand Up @@ -97,6 +114,7 @@
* @author Ruben Cervilla
* @author Luis De Bello
* @author Andrea Como
* @author Chris Bono
*/
public class LettuceConnectionFactory
implements InitializingBean, DisposableBean, RedisConnectionFactory, ReactiveRedisConnectionFactory {
Expand Down Expand Up @@ -279,6 +297,32 @@ public LettuceConnectionFactory(RedisClusterConfiguration clusterConfiguration,
this.configuration = clusterConfiguration;
}

/**
* Converts a {@link RedisURI} into its corresponding {@link RedisConfiguration} according to the following:
* <ul>
* <li>If {@code redisURI} has sentinel info a {@link RedisSentinelConfiguration} is returned</li>
* <li>If {@code redisURI} has socket info a {@link RedisSocketConfiguration} is returned</li>
* <li>Otherwise a {@link RedisStandaloneConfiguration} is returned</li>
* </ul>
*
* @param redisURI the connection info in the format of a RedisURI
* @return an appropriate {@link RedisConfiguration} instance representing the Redis URI.
*/
public static RedisConfiguration redisConfigurationFromRedisUri(RedisURI redisURI) {

Assert.notNull(redisURI, "RedisURI must not be null");

if (!ObjectUtils.isEmpty(redisURI.getSentinels())) {
return LettuceConverters.redisUriToSentinelConfiguration(redisURI);
}

if (!ObjectUtils.isEmpty(redisURI.getSocket())) {
return LettuceConverters.redisUriToSocketConfiguration(redisURI);
}

return LettuceConverters.redisUriToStandaloneConfiguration(redisURI);
}

/*
* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,43 @@
*/
package org.springframework.data.redis.connection.lettuce;

import io.lettuce.core.*;
import io.lettuce.core.cluster.models.partitions.Partitions;
import io.lettuce.core.cluster.models.partitions.RedisClusterNode.NodeFlag;

import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import io.lettuce.core.BitFieldArgs;
import io.lettuce.core.GeoArgs;
import io.lettuce.core.GeoCoordinates;
import io.lettuce.core.GeoWithin;
import io.lettuce.core.GetExArgs;
import io.lettuce.core.KeyScanArgs;
import io.lettuce.core.KeyValue;
import io.lettuce.core.LMoveArgs;
import io.lettuce.core.Limit;
import io.lettuce.core.Range;
import io.lettuce.core.RedisURI;
import io.lettuce.core.ScanArgs;
import io.lettuce.core.ScoredValue;
import io.lettuce.core.ScriptOutputType;
import io.lettuce.core.SetArgs;
import io.lettuce.core.SortArgs;
import io.lettuce.core.TransactionResult;
import io.lettuce.core.cluster.models.partitions.Partitions;
import io.lettuce.core.cluster.models.partitions.RedisClusterNode.NodeFlag;

import org.springframework.core.convert.converter.Converter;
import org.springframework.dao.DataAccessException;
import org.springframework.data.geo.Distance;
Expand All @@ -44,6 +71,7 @@
import org.springframework.data.redis.connection.RedisClusterNode.Flag;
import org.springframework.data.redis.connection.RedisClusterNode.LinkState;
import org.springframework.data.redis.connection.RedisClusterNode.SlotRange;
import org.springframework.data.redis.connection.RedisConfiguration;
import org.springframework.data.redis.connection.RedisGeoCommands.DistanceUnit;
import org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation;
import org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs;
Expand All @@ -54,6 +82,8 @@
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.RedisServer;
import org.springframework.data.redis.connection.RedisSocketConfiguration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.RedisStringCommands.SetOption;
import org.springframework.data.redis.connection.RedisZSetCommands;
import org.springframework.data.redis.connection.RedisZSetCommands.Range.Boundary;
Expand Down Expand Up @@ -85,6 +115,7 @@
* @author Mark Paluch
* @author Ninad Divadkar
* @author dengliming
* @author Chris Bono
*/
public abstract class LettuceConverters extends Converters {

Expand Down Expand Up @@ -535,6 +566,86 @@ public static RedisURI sentinelConfigurationToRedisURI(RedisSentinelConfiguratio
return builder.build();
}

/**
* Converts a {@link RedisURI} to its corresponding {@link RedisSentinelConfiguration}.
*
* @param redisURI the uri containing the Redis Sentinel connection info
* @return a {@link RedisSentinelConfiguration} representing the Redis Sentinel information in the Redis URI.
* @since 2.6
*/
public static RedisSentinelConfiguration redisUriToSentinelConfiguration(RedisURI redisURI) {

Assert.notNull(redisURI, "RedisURI is required");
Assert.hasText(redisURI.getSentinelMasterId(), "RedisURI must have sentinelMasterId param set");

RedisSentinelConfiguration sentinelConfiguration = new RedisSentinelConfiguration();
sentinelConfiguration.setMaster(redisURI.getSentinelMasterId());
sentinelConfiguration.setDatabase(redisURI.getDatabase());

for (RedisURI sentinelNodeRedisUri : redisURI.getSentinels()) {
RedisNode sentinelNode = new RedisNode(sentinelNodeRedisUri.getHost(), sentinelNodeRedisUri.getPort());
if (sentinelNodeRedisUri.getPassword() != null) {
sentinelConfiguration.setSentinelPassword(sentinelNodeRedisUri.getPassword());
}
sentinelConfiguration.addSentinel(sentinelNode);
}

applyAuthentication(redisURI, sentinelConfiguration);

return sentinelConfiguration;
}

/**
* Converts a {@link RedisURI} to its corresponding {@link RedisSocketConfiguration}.
*
* @param redisURI the uri containing the Redis connection info using a local unix domain socket
* @return a {@link RedisSocketConfiguration} representing the connection information in the Redis URI.
* @since 2.6
*/
public static RedisSocketConfiguration redisUriToSocketConfiguration(RedisURI redisURI) {

Assert.notNull(redisURI, "RedisURI is required");
Assert.hasText(redisURI.getSocket(), "RedisURI must have socket path set");

RedisSocketConfiguration socketConfiguration = new RedisSocketConfiguration();
socketConfiguration.setSocket(redisURI.getSocket());
socketConfiguration.setDatabase(redisURI.getDatabase());

applyAuthentication(redisURI, socketConfiguration);

return socketConfiguration;
}

/**
* Converts a {@link RedisURI} to its corresponding {@link RedisStandaloneConfiguration}.
*
* @param redisURI the uri containing the Redis connection info
* @return a {@link RedisStandaloneConfiguration} representing the connection information in the Redis URI.
* @since 2.6
*/
public static RedisStandaloneConfiguration redisUriToStandaloneConfiguration(RedisURI redisURI) {

Assert.notNull(redisURI, "RedisURI is required");

RedisStandaloneConfiguration standaloneConfiguration = new RedisStandaloneConfiguration();
standaloneConfiguration.setHostName(redisURI.getHost());
standaloneConfiguration.setPort(redisURI.getPort());
standaloneConfiguration.setDatabase(redisURI.getDatabase());

applyAuthentication(redisURI, standaloneConfiguration);

return standaloneConfiguration;
}

private static void applyAuthentication(RedisURI redisURI, RedisConfiguration.WithAuthentication redisConfiguration) {
if (StringUtils.hasText(redisURI.getUsername())) {
redisConfiguration.setUsername(redisURI.getUsername());
}
if (redisURI.getPassword() != null) {
redisConfiguration.setPassword(redisURI.getPassword());
}
}

public static byte[] toBytes(@Nullable String source) {
if (source == null) {
return null;
Expand Down