use of io.lettuce.core.models.role.RedisNodeDescription in project lettuce-core by lettuce-io.
the class Requests method onEmit.
@Override
protected void onEmit(Emission<List<RedisNodeDescription>> emission) {
List<RedisNodeDescription> result = new ArrayList<>();
Map<RedisNodeDescription, Long> latencies = new HashMap<>();
for (RedisNodeDescription node : nodes) {
TimedAsyncCommand<String, String, String> future = getRequest(node.getUri());
if (future == null || !future.isDone()) {
continue;
}
RedisNodeDescription redisNodeDescription = findNodeByUri(nodes, node.getUri());
latencies.put(redisNodeDescription, future.duration());
result.add(redisNodeDescription);
}
SortAction sortAction = SortAction.getSortAction();
sortAction.sort(result, new LatencyComparator(latencies));
emission.success(result);
}
use of io.lettuce.core.models.role.RedisNodeDescription in project lettuce-core by lettuce-io.
the class MasterReplicaTopologyRefresh method getConnections.
/*
* Establish connections asynchronously.
*/
private AsyncConnections getConnections(Iterable<RedisNodeDescription> nodes) {
List<RedisNodeDescription> 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<StatefulRedisConnection<String, String>> connectionFuture = nodeConnectionFactory.connectToNodeAsync(CODEC, redisURI);
CompletableFuture<StatefulRedisConnection<String, String>> 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;
}
use of io.lettuce.core.models.role.RedisNodeDescription in project LinkAgent by shulieTech.
the class SentinelConnectorInterceptor method doBefore.
@Override
public void doBefore(Advice advice) throws Throwable {
Object[] arrs = advice.getParameterArray();
try {
List<RedisNodeDescription> lists = (List<RedisNodeDescription>) arrs[4];
for (RedisNodeDescription nodeDescription : lists) {
RedisURI uri = nodeDescription.getUri();
LettuceUtils.cacheMasterSlave(uri);
}
} catch (Throwable t) {
}
}
use of io.lettuce.core.models.role.RedisNodeDescription in project lettuce-core by lettuce-io.
the class PooledClusterConnectionProvider method getReadConnection.
private CompletableFuture<StatefulRedisConnection<K, V>> getReadConnection(int slot) {
// avoid races when reconfiguring partitions.
CompletableFuture<StatefulRedisConnection<K, V>>[] readerCandidates;
boolean cached = true;
synchronized (stateLock) {
readerCandidates = readers[slot];
}
if (readerCandidates == null) {
RedisClusterNode upstream = partitions.getPartitionBySlot(slot);
if (upstream == null) {
clusterEventListener.onUncoveredSlot(slot);
return Futures.failed(new PartitionSelectorException(String.format("Cannot determine a partition to read for slot %d.", slot), partitions.clone()));
}
List<RedisNodeDescription> candidates = getReadCandidates(upstream);
List<RedisNodeDescription> selection = readFrom.select(new ReadFrom.Nodes() {
@Override
public List<RedisNodeDescription> getNodes() {
return candidates;
}
@Override
public Iterator<RedisNodeDescription> iterator() {
return candidates.iterator();
}
});
if (selection.isEmpty()) {
clusterEventListener.onUncoveredSlot(slot);
return Futures.failed(new PartitionSelectorException(String.format("Cannot determine a partition to read for slot %d with setting %s.", slot, readFrom), partitions.clone()));
}
readerCandidates = getReadFromConnections(selection);
cached = false;
}
CompletableFuture<StatefulRedisConnection<K, V>>[] selectedReaderCandidates = readerCandidates;
if (cached) {
return CompletableFuture.allOf(readerCandidates).thenCompose(v -> {
boolean orderSensitive = isOrderSensitive(selectedReaderCandidates);
if (!orderSensitive) {
CompletableFuture<StatefulRedisConnection<K, V>> candidate = findRandomActiveConnection(selectedReaderCandidates, Function.identity());
if (candidate != null) {
return candidate;
}
}
for (CompletableFuture<StatefulRedisConnection<K, V>> candidate : selectedReaderCandidates) {
if (candidate.join().isOpen()) {
return candidate;
}
}
return selectedReaderCandidates[0];
});
}
CompletableFuture<StatefulRedisConnection<K, V>[]> filteredReaderCandidates = new CompletableFuture<>();
CompletableFuture.allOf(readerCandidates).thenApply(v -> selectedReaderCandidates).whenComplete((candidates, throwable) -> {
if (throwable == null) {
filteredReaderCandidates.complete(getConnections(candidates));
return;
}
StatefulRedisConnection<K, V>[] connections = getConnections(selectedReaderCandidates);
if (connections.length == 0) {
filteredReaderCandidates.completeExceptionally(throwable);
return;
}
filteredReaderCandidates.complete(connections);
});
return filteredReaderCandidates.thenApply(statefulRedisConnections -> {
boolean orderSensitive = isOrderSensitive(statefulRedisConnections);
CompletableFuture<StatefulRedisConnection<K, V>>[] toCache = new CompletableFuture[statefulRedisConnections.length];
for (int i = 0; i < toCache.length; i++) {
toCache[i] = CompletableFuture.completedFuture(statefulRedisConnections[i]);
}
synchronized (stateLock) {
readers[slot] = toCache;
}
if (!orderSensitive) {
StatefulRedisConnection<K, V> candidate = findRandomActiveConnection(selectedReaderCandidates, CompletableFuture::join);
if (candidate != null) {
return candidate;
}
}
for (StatefulRedisConnection<K, V> candidate : statefulRedisConnections) {
if (candidate.isOpen()) {
return candidate;
}
}
return statefulRedisConnections[0];
});
}
use of io.lettuce.core.models.role.RedisNodeDescription in project lettuce-core by lettuce-io.
the class ClusterScanSupport method getNodeIds.
/**
* Retrieve a list of node Ids to use for the SCAN operation.
*
* @param connection
* @return
*/
private static List<String> getNodeIds(StatefulRedisClusterConnection<?, ?> connection) {
List<String> nodeIds = new ArrayList<>();
PartitionAccessor partitionAccessor = new PartitionAccessor(connection.getPartitions());
for (RedisClusterNode redisClusterNode : partitionAccessor.getUpstream()) {
if (connection.getReadFrom() != null) {
List<RedisNodeDescription> readCandidates = (List) partitionAccessor.getReadCandidates(redisClusterNode);
List<RedisNodeDescription> selection = connection.getReadFrom().select(new ReadFrom.Nodes() {
@Override
public List<RedisNodeDescription> getNodes() {
return readCandidates;
}
@Override
public Iterator<RedisNodeDescription> iterator() {
return readCandidates.iterator();
}
});
if (!selection.isEmpty()) {
int indexToUse = 0;
if (!OrderingReadFromAccessor.isOrderSensitive(connection.getReadFrom())) {
indexToUse = ThreadLocalRandom.current().nextInt(selection.size());
}
RedisClusterNode selectedNode = (RedisClusterNode) selection.get(indexToUse);
nodeIds.add(selectedNode.getNodeId());
continue;
}
}
nodeIds.add(redisClusterNode.getNodeId());
}
return nodeIds;
}
Aggregations