
io.lettuce.core.masterreplica.MasterReplicaTopologyRefresh Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of lettuce-core Show documentation
Show all versions of lettuce-core Show documentation
Advanced and thread-safe Java Redis client for synchronous, asynchronous, and
reactive usage. Supports Cluster, Sentinel, Pipelining, Auto-Reconnect, Codecs
and much more.
The newest version!
package io.lettuce.core.masterreplica;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ScheduledExecutorService;
import reactor.core.publisher.Mono;
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisConnectionException;
import io.lettuce.core.RedisURI;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.cluster.models.partitions.Partitions;
import io.lettuce.core.codec.StringCodec;
import io.lettuce.core.internal.LettuceLists;
import io.lettuce.core.models.role.RedisNodeDescription;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
/**
* Utility to refresh the Master-Replica topology view based on {@link RedisNodeDescription}.
*
* @author Mark Paluch
*/
class MasterReplicaTopologyRefresh {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(MasterReplicaTopologyRefresh.class);
private static final StringCodec CODEC = StringCodec.UTF8;
private final NodeConnectionFactory nodeConnectionFactory;
private final TopologyProvider topologyProvider;
private final ScheduledExecutorService eventExecutors;
MasterReplicaTopologyRefresh(RedisClient client, TopologyProvider topologyProvider) {
this(new RedisClientNodeConnectionFactory(client), client.getResources().eventExecutorGroup(), topologyProvider);
}
MasterReplicaTopologyRefresh(NodeConnectionFactory nodeConnectionFactory, ScheduledExecutorService eventExecutors,
TopologyProvider topologyProvider) {
this.nodeConnectionFactory = nodeConnectionFactory;
this.eventExecutors = eventExecutors;
this.topologyProvider = topologyProvider;
}
/**
* Load master replica nodes. Result contains an ordered list of {@link RedisNodeDescription}s. The sort key is the latency.
* Nodes with lower latency come first.
*
* @param seed collection of {@link RedisURI}s
* @return mapping between {@link RedisURI} and {@link Partitions}
*/
public Mono> getNodes(RedisURI seed) {
CompletableFuture> future = topologyProvider.getNodesAsync();
Mono> initialNodes = Mono.fromFuture(future).doOnNext(nodes -> {
applyAuthenticationCredentials(nodes, seed);
});
return initialNodes.map(this::getConnections)
.flatMap(asyncConnections -> asyncConnections.asMono(seed.getTimeout(), eventExecutors))
.flatMap(connections -> {
Requests requests = connections.requestPing();
CompletionStage> nodes = requests.getOrTimeout(seed.getTimeout(),
eventExecutors);
return Mono.fromCompletionStage(nodes).flatMap(it -> ResumeAfter.close(connections).thenEmit(it));
});
}
/*
* Establish connections asynchronously.
*/
private AsyncConnections getConnections(Iterable nodes) {
List nodeList = LettuceLists.newList(nodes);
AsyncConnections connections = new AsyncConnections(nodeList);
for (RedisNodeDescription node : nodeList) {
RedisURI redisURI = node.getUri();
String message = String.format("Unable to connect to %s", redisURI);
try {
CompletableFuture> connectionFuture = nodeConnectionFactory
.connectToNodeAsync(CODEC, redisURI);
CompletableFuture> sync = new CompletableFuture<>();
connectionFuture.whenComplete((connection, throwable) -> {
if (throwable != null) {
if (throwable instanceof RedisConnectionException) {
if (logger.isDebugEnabled()) {
logger.debug(throwable.getMessage(), throwable);
} else {
logger.warn(throwable.getMessage());
}
} else {
logger.warn(message, throwable);
}
sync.completeExceptionally(new RedisConnectionException(message, throwable));
} else {
connection.async().clientSetname("lettuce#MasterReplicaTopologyRefresh");
sync.complete(connection);
}
});
connections.addConnection(redisURI, sync);
} catch (RuntimeException e) {
logger.warn(String.format(message, redisURI), e);
}
}
return connections;
}
private static void applyAuthenticationCredentials(List nodes, RedisURI seed) {
for (RedisNodeDescription node : nodes) {
node.getUri().applyAuthentication(seed);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy