DATAREDIS-580 - Support Master/Slave connections with ReadFrom settings using Lettuce.
We now allow configuration of ReadFrom settings using the Lettuce driver to enable slave reads. If ReadFrom is configured, we opt-in to Master/Slave connections instead of plain connections. Master/Slave connections route commands to the configured type of node depending on whether the command is a read or write command. LettuceClientConfiguration configuration = LettuceClientConfiguration.builder().readFrom(ReadFrom.SLAVE).build(); ReadFrom is available for: * Static Master/Slave Redis without Redis Sentinel * Sentinel-Managed Master/Slave Redis * Redis Cluster ReadFrom is not configured for Pub/Sub connections or connections to the actual Sentinel servers. Original Pull Request: #287
This commit is contained in:
committed by
Christoph Strobl
parent
9775734f6f
commit
b414fdf6f1
@@ -15,11 +15,15 @@
|
||||
*/
|
||||
package org.springframework.data.redis.connection.lettuce;
|
||||
|
||||
import io.lettuce.core.ReadFrom;
|
||||
import io.lettuce.core.api.StatefulConnection;
|
||||
import io.lettuce.core.cluster.RedisClusterClient;
|
||||
import io.lettuce.core.cluster.api.StatefulRedisClusterConnection;
|
||||
import io.lettuce.core.codec.RedisCodec;
|
||||
import io.lettuce.core.pubsub.StatefulRedisPubSubConnection;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Connection provider for Cluster connections.
|
||||
@@ -28,16 +32,12 @@ import io.lettuce.core.pubsub.StatefulRedisPubSubConnection;
|
||||
* @author Christoph Strobl
|
||||
* @since 2.0
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
class ClusterConnectionProvider implements LettuceConnectionProvider {
|
||||
|
||||
private final RedisClusterClient client;
|
||||
private final RedisCodec<?, ?> codec;
|
||||
|
||||
ClusterConnectionProvider(RedisClusterClient client, RedisCodec<?, ?> codec) {
|
||||
|
||||
this.client = client;
|
||||
this.codec = codec;
|
||||
}
|
||||
private final Optional<ReadFrom> readFrom;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
@@ -52,7 +52,11 @@ class ClusterConnectionProvider implements LettuceConnectionProvider {
|
||||
|
||||
if (StatefulRedisClusterConnection.class.isAssignableFrom(connectionType)
|
||||
|| connectionType.equals(StatefulConnection.class)) {
|
||||
return connectionType.cast(client.connect(codec));
|
||||
|
||||
StatefulRedisClusterConnection<?, ?> connection = client.connect(codec);
|
||||
readFrom.ifPresent(connection::setReadFrom);
|
||||
|
||||
return connectionType.cast(connection);
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException("Connection type " + connectionType + " not supported!");
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.redis.connection.lettuce;
|
||||
|
||||
import io.lettuce.core.ClientOptions;
|
||||
import io.lettuce.core.ReadFrom;
|
||||
import io.lettuce.core.resource.ClientResources;
|
||||
|
||||
import java.time.Duration;
|
||||
@@ -38,11 +39,13 @@ class DefaultLettuceClientConfiguration implements LettuceClientConfiguration {
|
||||
private final Optional<ClientResources> clientResources;
|
||||
private final Optional<ClientOptions> clientOptions;
|
||||
private final Optional<String> clientName;
|
||||
private final Optional<ReadFrom> readFrom;
|
||||
private final Duration timeout;
|
||||
private final Duration shutdownTimeout;
|
||||
|
||||
DefaultLettuceClientConfiguration(boolean useSsl, boolean verifyPeer, boolean startTls,
|
||||
@Nullable ClientResources clientResources, @Nullable ClientOptions clientOptions, @Nullable String clientName,
|
||||
@Nullable ReadFrom readFrom,
|
||||
Duration timeout, Duration shutdownTimeout) {
|
||||
|
||||
this.useSsl = useSsl;
|
||||
@@ -51,6 +54,7 @@ class DefaultLettuceClientConfiguration implements LettuceClientConfiguration {
|
||||
this.clientResources = Optional.ofNullable(clientResources);
|
||||
this.clientOptions = Optional.ofNullable(clientOptions);
|
||||
this.clientName = Optional.ofNullable(clientName);
|
||||
this.readFrom = Optional.ofNullable(readFrom);
|
||||
this.timeout = timeout;
|
||||
this.shutdownTimeout = shutdownTimeout;
|
||||
}
|
||||
@@ -91,8 +95,7 @@ class DefaultLettuceClientConfiguration implements LettuceClientConfiguration {
|
||||
return clientResources;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration#getClientOptions()
|
||||
*/
|
||||
@Override
|
||||
@@ -109,6 +112,15 @@ class DefaultLettuceClientConfiguration implements LettuceClientConfiguration {
|
||||
return clientName;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration#getReadFrom()
|
||||
*/
|
||||
@Override
|
||||
public Optional<ReadFrom> getReadFrom() {
|
||||
return readFrom;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration#getTimeout()
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.redis.connection.lettuce;
|
||||
|
||||
import io.lettuce.core.ClientOptions;
|
||||
import io.lettuce.core.ReadFrom;
|
||||
import io.lettuce.core.resource.ClientResources;
|
||||
|
||||
import java.time.Duration;
|
||||
@@ -96,6 +97,15 @@ class DefaultLettucePoolingClientConfiguration implements LettucePoolingClientCo
|
||||
return clientConfiguration.getClientName();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration#getReadFrom()
|
||||
*/
|
||||
@Override
|
||||
public Optional<ReadFrom> getReadFrom() {
|
||||
return clientConfiguration.getReadFrom();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration#getCommandTimeout()
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.redis.connection.lettuce;
|
||||
|
||||
import io.lettuce.core.ClientOptions;
|
||||
import io.lettuce.core.ReadFrom;
|
||||
import io.lettuce.core.RedisURI;
|
||||
import io.lettuce.core.resource.ClientResources;
|
||||
|
||||
@@ -38,6 +39,7 @@ import org.springframework.util.Assert;
|
||||
* <li>Optional {@link ClientResources}</li>
|
||||
* <li>Optional {@link ClientOptions}</li>
|
||||
* <li>Optional client name</li>
|
||||
* <li>Optional {@link ReadFrom}. Enables Master/Slave operations if configured.</li>
|
||||
* <li>Client {@link Duration timeout}</li>
|
||||
* <li>Shutdown {@link Duration timeout}</li>
|
||||
* </ul>
|
||||
@@ -82,6 +84,12 @@ public interface LettuceClientConfiguration {
|
||||
*/
|
||||
Optional<String> getClientName();
|
||||
|
||||
/**
|
||||
* @return the optional {@link io.lettuce.core.ReadFrom} setting.
|
||||
* @since 2.1
|
||||
*/
|
||||
Optional<ReadFrom> getReadFrom();
|
||||
|
||||
/**
|
||||
* @return the timeout.
|
||||
*/
|
||||
@@ -118,6 +126,8 @@ public interface LettuceClientConfiguration {
|
||||
* <dd>none</dd>
|
||||
* <dt>Client name</dt>
|
||||
* <dd>none</dd>
|
||||
* <dt>Read From</dt>
|
||||
* <dd>none</dd>
|
||||
* <dt>Connect Timeout</dt>
|
||||
* <dd>60 Seconds</dd>
|
||||
* <dt>Shutdown Timeout</dt>
|
||||
@@ -142,6 +152,7 @@ public interface LettuceClientConfiguration {
|
||||
@Nullable ClientResources clientResources;
|
||||
@Nullable ClientOptions clientOptions;
|
||||
@Nullable String clientName;
|
||||
@Nullable ReadFrom readFrom;
|
||||
Duration timeout = Duration.ofSeconds(RedisURI.DEFAULT_TIMEOUT);
|
||||
Duration shutdownTimeout = Duration.ofMillis(100);
|
||||
|
||||
@@ -188,6 +199,22 @@ public interface LettuceClientConfiguration {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure {@link ReadFrom}. Enables Master/Slave operations if configured.
|
||||
*
|
||||
* @param readFrom must not be {@literal null}.
|
||||
* @return {@literal this} builder.
|
||||
* @throws IllegalArgumentException if clientOptions is {@literal null}.
|
||||
* @since 2.1
|
||||
*/
|
||||
public LettuceClientConfigurationBuilder readFrom(ReadFrom readFrom) {
|
||||
|
||||
Assert.notNull(readFrom, "ReadFrom must not be null!");
|
||||
|
||||
this.readFrom = readFrom;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure a {@code clientName} to be set with {@code CLIENT SETNAME}.
|
||||
*
|
||||
@@ -242,7 +269,7 @@ public interface LettuceClientConfiguration {
|
||||
public LettuceClientConfiguration build() {
|
||||
|
||||
return new DefaultLettuceClientConfiguration(useSsl, verifyPeer, startTls, clientResources, clientOptions,
|
||||
clientName, timeout, shutdownTimeout);
|
||||
clientName, readFrom, timeout, shutdownTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
@@ -74,7 +75,7 @@ public class LettuceClusterConnection extends LettuceConnection implements Defau
|
||||
* @param clusterClient must not be {@literal null}.
|
||||
*/
|
||||
public LettuceClusterConnection(RedisClusterClient clusterClient) {
|
||||
this(new ClusterConnectionProvider(clusterClient, CODEC));
|
||||
this(new ClusterConnectionProvider(clusterClient, CODEC, Optional.empty()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,7 +99,7 @@ public class LettuceClusterConnection extends LettuceConnection implements Defau
|
||||
* @since 2.0
|
||||
*/
|
||||
public LettuceClusterConnection(RedisClusterClient clusterClient, ClusterCommandExecutor executor, Duration timeout) {
|
||||
this(new ClusterConnectionProvider(clusterClient, CODEC), executor, timeout);
|
||||
this(new ClusterConnectionProvider(clusterClient, CODEC, Optional.empty()), executor, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -49,6 +49,7 @@ import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Future;
|
||||
@@ -224,7 +225,7 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
if (pool != null) {
|
||||
this.connectionProvider = new LettucePoolConnectionProvider(pool);
|
||||
} else {
|
||||
this.connectionProvider = new StandaloneConnectionProvider((RedisClient) client, CODEC);
|
||||
this.connectionProvider = new StandaloneConnectionProvider((RedisClient) client, CODEC, Optional.empty());
|
||||
}
|
||||
|
||||
this.asyncSharedConn = sharedConnection;
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.redis.connection.lettuce;
|
||||
|
||||
import io.lettuce.core.AbstractRedisClient;
|
||||
import io.lettuce.core.ClientOptions;
|
||||
import io.lettuce.core.ReadFrom;
|
||||
import io.lettuce.core.RedisClient;
|
||||
import io.lettuce.core.RedisException;
|
||||
import io.lettuce.core.RedisURI;
|
||||
@@ -887,7 +888,7 @@ public class LettuceConnectionFactory
|
||||
|
||||
private LettuceConnectionProvider createConnectionProvider(AbstractRedisClient client, RedisCodec<?, ?> codec) {
|
||||
|
||||
LettuceConnectionProvider connectionProvider = doConnectionProvider(client, codec);
|
||||
LettuceConnectionProvider connectionProvider = doCreateConnectionProvider(client, codec);
|
||||
|
||||
if (this.clientConfiguration instanceof LettucePoolingClientConfiguration) {
|
||||
return new LettucePoolingConnectionProvider(connectionProvider,
|
||||
@@ -897,13 +898,26 @@ public class LettuceConnectionFactory
|
||||
return connectionProvider;
|
||||
}
|
||||
|
||||
private LettuceConnectionProvider doConnectionProvider(AbstractRedisClient client, RedisCodec<?, ?> codec) {
|
||||
|
||||
/**
|
||||
* Create a {@link LettuceConnectionProvider } given {@link AbstractRedisClient} and {@link RedisCodec}. Configuration
|
||||
* of this connection factory specifies the type of the created connection provider. This method creates either a
|
||||
* {@link LettuceConnectionProvider} for either {@link RedisClient} or {@link RedisClusterClient}. Subclasses may
|
||||
* override this method to decorate the connection provider.
|
||||
*
|
||||
* @param client either {@link RedisClient} or {@link RedisClusterClient}, must not be {@literal null}.
|
||||
* @param codec used for connection creation, must not be {@literal null}. By default, a {@code byte[]} codec.
|
||||
* Reactive connections require a {@link java.nio.ByteBuffer} codec.
|
||||
* @return the connection provider.
|
||||
* @since 2.1
|
||||
* @see io.lettuce.core.codec.ByteArrayCodec
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceReactiveRedisConnection.ByteBufferCodec
|
||||
*/
|
||||
protected LettuceConnectionProvider doCreateConnectionProvider(AbstractRedisClient client, RedisCodec<?, ?> codec) {Optional<ReadFrom> readFrom = getClientConfiguration().getReadFrom();
|
||||
if (isClusterAware()) {
|
||||
return new ClusterConnectionProvider((RedisClusterClient) client, codec);
|
||||
return new ClusterConnectionProvider((RedisClusterClient) client, codec, readFrom);
|
||||
}
|
||||
|
||||
return new StandaloneConnectionProvider((RedisClient) client, codec);
|
||||
return new StandaloneConnectionProvider((RedisClient) client, codec, readFrom);
|
||||
}
|
||||
|
||||
private AbstractRedisClient createClient() {
|
||||
@@ -1202,6 +1216,14 @@ public class LettuceConnectionFactory
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration#getReadFrom()
|
||||
*/
|
||||
@Override
|
||||
public Optional<ReadFrom> getReadFrom() {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration#getClientName()
|
||||
|
||||
@@ -15,14 +15,20 @@
|
||||
*/
|
||||
package org.springframework.data.redis.connection.lettuce;
|
||||
|
||||
import io.lettuce.core.ReadFrom;
|
||||
import io.lettuce.core.RedisClient;
|
||||
import io.lettuce.core.RedisURI;
|
||||
import io.lettuce.core.api.StatefulConnection;
|
||||
import io.lettuce.core.codec.RedisCodec;
|
||||
import io.lettuce.core.masterslave.MasterSlave;
|
||||
import io.lettuce.core.masterslave.StatefulRedisMasterSlaveConnection;
|
||||
import io.lettuce.core.pubsub.StatefulRedisPubSubConnection;
|
||||
import io.lettuce.core.sentinel.api.StatefulRedisSentinelConnection;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionProvider.TargetAware;
|
||||
|
||||
/**
|
||||
@@ -35,6 +41,7 @@ class StandaloneConnectionProvider implements LettuceConnectionProvider, TargetA
|
||||
|
||||
private final RedisClient client;
|
||||
private final RedisCodec<?, ?> codec;
|
||||
private final Optional<ReadFrom> readFrom;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
@@ -53,7 +60,17 @@ class StandaloneConnectionProvider implements LettuceConnectionProvider, TargetA
|
||||
}
|
||||
|
||||
if (StatefulConnection.class.isAssignableFrom(connectionType)) {
|
||||
return connectionType.cast(client.connect(codec));
|
||||
|
||||
return readFrom.map(it -> {
|
||||
|
||||
DirectFieldAccessor fieldAccessor = new DirectFieldAccessor(client);
|
||||
RedisURI redisURI = RedisURI.class.cast(fieldAccessor.getPropertyValue("redisURI"));
|
||||
|
||||
StatefulRedisMasterSlaveConnection<?, ?> connection = MasterSlave.connect(client, codec, redisURI);
|
||||
connection.setReadFrom(it);
|
||||
|
||||
return connectionType.cast(connection);
|
||||
}).orElseGet(() -> connectionType.cast(client.connect(codec)));
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException("Connection type " + connectionType + " not supported!");
|
||||
|
||||
@@ -23,6 +23,7 @@ import static org.junit.Assume.*;
|
||||
|
||||
import io.lettuce.core.EpollProvider;
|
||||
import io.lettuce.core.KqueueProvider;
|
||||
import io.lettuce.core.ReadFrom;
|
||||
import io.lettuce.core.RedisException;
|
||||
import io.lettuce.core.api.async.RedisAsyncCommands;
|
||||
import io.lettuce.core.api.reactive.BaseRedisReactiveCommands;
|
||||
@@ -385,6 +386,28 @@ public class LettuceConnectionFactoryTests {
|
||||
factory.destroy();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-580
|
||||
public void factoryUsesMasterSlaveConnections() {
|
||||
|
||||
LettuceClientConfiguration configuration = LettuceTestClientConfiguration.builder().readFrom(ReadFrom.SLAVE)
|
||||
.build();
|
||||
|
||||
LettuceConnectionFactory factory = new LettuceConnectionFactory(SettingsUtils.standaloneConfiguration(),
|
||||
configuration);
|
||||
factory.afterPropertiesSet();
|
||||
|
||||
RedisConnection connection = factory.getConnection();
|
||||
|
||||
try {
|
||||
assertThat(connection.ping(), is(equalTo("PONG")));
|
||||
assertThat(connection.info().getProperty("role"), is(equalTo("slave")));
|
||||
} finally {
|
||||
this.connection.close();
|
||||
}
|
||||
|
||||
factory.destroy();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-576
|
||||
public void connectionAppliesClientName() {
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ import io.lettuce.core.api.sync.RedisCommands;
|
||||
import io.lettuce.core.cluster.api.sync.RedisAdvancedClusterCommands;
|
||||
import io.lettuce.core.cluster.api.sync.RedisClusterCommands;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.ClassRule;
|
||||
@@ -43,7 +45,8 @@ public abstract class LettuceReactiveClusterCommandsTestsBase {
|
||||
assumeThat(clientProvider.test(), is(true));
|
||||
nativeCommands = clientProvider.getClient().connect().sync();
|
||||
connection = new LettuceReactiveRedisClusterConnection(
|
||||
new ClusterConnectionProvider(clientProvider.getClient(), LettuceReactiveRedisConnection.CODEC),
|
||||
new ClusterConnectionProvider(clientProvider.getClient(), LettuceReactiveRedisConnection.CODEC,
|
||||
Optional.empty()),
|
||||
clientProvider.getClient());
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@@ -89,9 +90,9 @@ public abstract class LettuceReactiveCommandsTestsBase {
|
||||
List<Object[]> parameters = new ArrayList<>();
|
||||
|
||||
StandaloneConnectionProvider standaloneProvider = new StandaloneConnectionProvider(standalone.getClient(),
|
||||
LettuceReactiveRedisConnection.CODEC);
|
||||
LettuceReactiveRedisConnection.CODEC, Optional.empty());
|
||||
StandaloneConnectionProvider nativeConnectionProvider = new StandaloneConnectionProvider(standalone.getClient(),
|
||||
StringCodec.UTF8);
|
||||
StringCodec.UTF8, Optional.empty());
|
||||
|
||||
parameters.add(new Object[] { standaloneProvider, nativeConnectionProvider, "Standalone" });
|
||||
parameters.add(new Object[] {
|
||||
@@ -101,9 +102,9 @@ public abstract class LettuceReactiveCommandsTestsBase {
|
||||
if (cluster.test()) {
|
||||
|
||||
ClusterConnectionProvider clusterProvider = new ClusterConnectionProvider(cluster.getClient(),
|
||||
LettuceReactiveRedisConnection.CODEC);
|
||||
LettuceReactiveRedisConnection.CODEC, Optional.empty());
|
||||
ClusterConnectionProvider nativeClusterConnectionProvider = new ClusterConnectionProvider(cluster.getClient(),
|
||||
StringCodec.UTF8);
|
||||
StringCodec.UTF8, Optional.empty());
|
||||
|
||||
parameters.add(new Object[] { clusterProvider, nativeClusterConnectionProvider, "Cluster" });
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ import static org.hamcrest.core.Is.is;
|
||||
import static org.hamcrest.core.IsEqual.equalTo;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import io.lettuce.core.ReadFrom;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -33,8 +35,10 @@ import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
import org.springframework.data.redis.ConnectionFactoryTracker;
|
||||
import org.springframework.data.redis.SettingsUtils;
|
||||
import org.springframework.data.redis.connection.AbstractConnectionIntegrationTests;
|
||||
import org.springframework.data.redis.connection.DefaultStringRedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
|
||||
import org.springframework.data.redis.connection.RedisSentinelConnection;
|
||||
import org.springframework.data.redis.connection.RedisServer;
|
||||
@@ -170,4 +174,64 @@ public class LettuceSentinelIntegrationTests extends AbstractConnectionIntegrati
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-580
|
||||
public void factoryWithReadFromMasterSettings() {
|
||||
|
||||
LettuceConnectionFactory factory = new LettuceConnectionFactory(SENTINEL_CONFIG,
|
||||
LettuceTestClientConfiguration.builder().readFrom(ReadFrom.MASTER).build());
|
||||
factory.afterPropertiesSet();
|
||||
|
||||
ConnectionFactoryTracker.add(factory);
|
||||
|
||||
StringRedisConnection connection = new DefaultStringRedisConnection(factory.getConnection());
|
||||
|
||||
try {
|
||||
assertThat(connection.ping(), is(equalTo("PONG")));
|
||||
assertThat(connection.info().getProperty("role"), is(equalTo("master")));
|
||||
} finally {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-580
|
||||
public void factoryWithReadFromSlaveSettings() {
|
||||
|
||||
LettuceConnectionFactory factory = new LettuceConnectionFactory(SENTINEL_CONFIG,
|
||||
LettuceTestClientConfiguration.builder().readFrom(ReadFrom.SLAVE).build());
|
||||
factory.afterPropertiesSet();
|
||||
|
||||
ConnectionFactoryTracker.add(factory);
|
||||
|
||||
StringRedisConnection connection = new DefaultStringRedisConnection(factory.getConnection());
|
||||
|
||||
try {
|
||||
assertThat(connection.ping(), is(equalTo("PONG")));
|
||||
assertThat(connection.info().getProperty("role"), is(equalTo("slave")));
|
||||
} finally {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-580
|
||||
public void factoryUsesMasterSlaveConnections() {
|
||||
|
||||
LettuceClientConfiguration configuration = LettuceTestClientConfiguration.builder().readFrom(ReadFrom.SLAVE)
|
||||
.build();
|
||||
|
||||
LettuceConnectionFactory factory = new LettuceConnectionFactory(SettingsUtils.standaloneConfiguration(),
|
||||
configuration);
|
||||
factory.afterPropertiesSet();
|
||||
|
||||
RedisConnection connection = factory.getConnection();
|
||||
|
||||
try {
|
||||
assertThat(connection.ping(), is(equalTo("PONG")));
|
||||
assertThat(connection.info().getProperty("role"), is(equalTo("slave")));
|
||||
} finally {
|
||||
this.connection.close();
|
||||
}
|
||||
|
||||
factory.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ package org.springframework.data.redis.test.util;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
|
||||
import redis.clients.jedis.Jedis;
|
||||
|
||||
import org.junit.Assume;
|
||||
import org.junit.rules.ExternalResource;
|
||||
import org.junit.rules.TestRule;
|
||||
@@ -24,8 +26,6 @@ import org.springframework.data.redis.connection.RedisClusterConfiguration;
|
||||
import org.springframework.data.redis.connection.RedisNode;
|
||||
import org.springframework.data.redis.connection.jedis.JedisConverters;
|
||||
|
||||
import redis.clients.jedis.Jedis;
|
||||
|
||||
/**
|
||||
* Simple {@link TestRule} implementation that check Redis is running in cluster mode.
|
||||
*
|
||||
@@ -59,7 +59,7 @@ public class RedisClusterRule extends ExternalResource {
|
||||
* @see org.junit.rules.ExternalResource#before()
|
||||
*/
|
||||
@Override
|
||||
protected void before() throws Throwable {
|
||||
public void before() {
|
||||
Assume.assumeThat(mode, is("cluster"));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user