
io.lettuce.core.masterreplica.StaticMasterReplicaTopologyProvider 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.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import reactor.core.publisher.Flux;
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.codec.StringCodec;
import io.lettuce.core.internal.Exceptions;
import io.lettuce.core.internal.LettuceAssert;
import io.lettuce.core.models.role.RedisNodeDescription;
import io.lettuce.core.models.role.RoleParser;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
/**
* Topology provider for a static node collection. This provider uses a static collection of nodes to determine the role of each
* {@link RedisURI node}. Node roles may change during runtime but the configuration must remain the same. This
* {@link TopologyProvider} does not auto-discover nodes.
*
* @author Mark Paluch
* @author Adam McElwee
*/
class StaticMasterReplicaTopologyProvider implements TopologyProvider {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(StaticMasterReplicaTopologyProvider.class);
private final RedisClient redisClient;
private final Iterable redisURIs;
public StaticMasterReplicaTopologyProvider(RedisClient redisClient, Iterable redisURIs) {
LettuceAssert.notNull(redisClient, "RedisClient must not be null");
LettuceAssert.notNull(redisURIs, "RedisURIs must not be null");
LettuceAssert.notNull(redisURIs.iterator().hasNext(), "RedisURIs must not be empty");
this.redisClient = redisClient;
this.redisURIs = redisURIs;
}
@Override
@SuppressWarnings("rawtypes")
public List getNodes() {
RedisURI next = redisURIs.iterator().next();
try {
return getNodesAsync().get(next.getTimeout().toMillis(), TimeUnit.MILLISECONDS);
} catch (Exception e) {
throw Exceptions.bubble(e);
}
}
@Override
public CompletableFuture> getNodesAsync() {
List> connections = new CopyOnWriteArrayList<>();
Flux uris = Flux.fromIterable(redisURIs);
Mono> nodes = uris.flatMap(uri -> getNodeDescription(connections, uri)).collectList()
.flatMap((nodeDescriptions) -> {
if (nodeDescriptions.isEmpty()) {
return Mono.error(new RedisConnectionException(
String.format("Failed to connect to at least one node in %s", redisURIs)));
}
return Mono.just(nodeDescriptions);
});
return nodes.toFuture();
}
private Mono getNodeDescription(List> connections,
RedisURI uri) {
return Mono.fromCompletionStage(redisClient.connectAsync(StringCodec.UTF8, uri)) //
.onErrorResume(t -> {
logger.warn("Cannot connect to {}", uri, t);
return Mono.empty();
}) //
.doOnNext(connections::add) //
.flatMap(connection -> {
Mono instance = getNodeDescription(uri, connection);
return instance.flatMap(it -> ResumeAfter.close(connection).thenEmit(it)).doFinally(s -> {
connections.remove(connection);
});
});
}
private static Mono getNodeDescription(RedisURI uri,
StatefulRedisConnection connection) {
return connection.reactive().role().collectList().map(RoleParser::parse)
.map(it -> new RedisMasterReplicaNode(uri.getHost(), uri.getPort(), uri, it.getRole()));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy