use of io.lettuce.core.internal.HostAndPort in project lettuce-core by lettuce-io.
the class ClusterDistributionChannelWriter method doWrite.
private <K, V, T> RedisCommand<K, V, T> doWrite(RedisCommand<K, V, T> command) {
if (command instanceof ClusterCommand && !command.isDone()) {
ClusterCommand<K, V, T> clusterCommand = (ClusterCommand<K, V, T>) command;
if (clusterCommand.isMoved() || clusterCommand.isAsk()) {
HostAndPort target;
boolean asking;
ByteBuffer firstEncodedKey = clusterCommand.getArgs().getFirstEncodedKey();
String keyAsString = null;
int slot = -1;
if (firstEncodedKey != null) {
firstEncodedKey.mark();
keyAsString = StringCodec.UTF8.decodeKey(firstEncodedKey);
firstEncodedKey.reset();
slot = getSlot(firstEncodedKey);
}
if (clusterCommand.isMoved()) {
target = getMoveTarget(clusterCommand.getError());
clusterEventListener.onMovedRedirection();
asking = false;
publish(new MovedRedirectionEvent(clusterCommand.getType().name(), keyAsString, slot, clusterCommand.getError()));
} else {
target = getAskTarget(clusterCommand.getError());
asking = true;
clusterEventListener.onAskRedirection();
publish(new AskRedirectionEvent(clusterCommand.getType().name(), keyAsString, slot, clusterCommand.getError()));
}
command.getOutput().setError((String) null);
CompletableFuture<StatefulRedisConnection<K, V>> connectFuture = asyncClusterConnectionProvider.getConnectionAsync(Intent.WRITE, target.getHostText(), target.getPort());
if (isSuccessfullyCompleted(connectFuture)) {
writeCommand(command, asking, connectFuture.join(), null);
} else {
connectFuture.whenComplete((connection, throwable) -> writeCommand(command, asking, connection, throwable));
}
return command;
}
}
ClusterCommand<K, V, T> commandToSend = getCommandToSend(command);
CommandArgs<K, V> args = command.getArgs();
// exclude CLIENT commands from cluster routing
if (args != null && !CommandType.CLIENT.equals(commandToSend.getType())) {
ByteBuffer encodedKey = args.getFirstEncodedKey();
if (encodedKey != null) {
int hash = getSlot(encodedKey);
Intent intent = getIntent(command.getType());
CompletableFuture<StatefulRedisConnection<K, V>> connectFuture = ((AsyncClusterConnectionProvider) clusterConnectionProvider).getConnectionAsync(intent, hash);
if (isSuccessfullyCompleted(connectFuture)) {
writeCommand(commandToSend, false, connectFuture.join(), null);
} else {
connectFuture.whenComplete((connection, throwable) -> writeCommand(commandToSend, false, connection, throwable));
}
return commandToSend;
}
}
writeCommand(commandToSend, defaultWriter);
return commandToSend;
}
use of io.lettuce.core.internal.HostAndPort in project lettuce-core by lettuce-io.
the class RedisClusterURIUtil method toRedisURIs.
/**
* Parse a Redis Cluster URI with potentially multiple hosts into a {@link List} of {@link RedisURI}.
*
* An URI follows the syntax: {@code redis://[password@]host[:port][,host2[:port2]]}
*
* @param uri must not be empty or {@code null}.
* @return {@link List} of {@link RedisURI}.
*/
public static List<RedisURI> toRedisURIs(URI uri) {
RedisURI redisURI = RedisURI.create(uri);
String[] parts = redisURI.getHost().split("\\,");
List<RedisURI> redisURIs = new ArrayList<>(parts.length);
for (String part : parts) {
HostAndPort hostAndPort = HostAndPort.parse(part);
RedisURI nodeUri = RedisURI.create(hostAndPort.getHostText(), hostAndPort.hasPort() ? hostAndPort.getPort() : redisURI.getPort());
applyUriConnectionSettings(redisURI, nodeUri);
redisURIs.add(nodeUri);
}
return redisURIs;
}
use of io.lettuce.core.internal.HostAndPort in project lettuce-core by lettuce-io.
the class ClusterPartitionParser method parseNode.
private static RedisClusterNode parseNode(String nodeInformation) {
Iterator<String> iterator = Arrays.asList(nodeInformation.split(" ")).iterator();
String nodeId = iterator.next();
boolean connected = false;
RedisURI uri = null;
String hostAndPortPart = iterator.next();
if (hostAndPortPart.contains("@")) {
hostAndPortPart = hostAndPortPart.substring(0, hostAndPortPart.indexOf('@'));
}
HostAndPort hostAndPort = HostAndPort.parseCompat(hostAndPortPart);
if (LettuceStrings.isNotEmpty(hostAndPort.getHostText())) {
uri = RedisURI.Builder.redis(hostAndPort.getHostText(), hostAndPort.getPort()).build();
}
String flags = iterator.next();
List<String> flagStrings = LettuceLists.newList(flags.split("\\,"));
Set<RedisClusterNode.NodeFlag> nodeFlags = readFlags(flagStrings);
// (nodeId or -)
String replicaOfString = iterator.next();
String replicaOf = "-".equals(replicaOfString) ? null : replicaOfString;
long pingSentTs = getLongFromIterator(iterator, 0);
long pongReceivedTs = getLongFromIterator(iterator, 0);
long configEpoch = getLongFromIterator(iterator, 0);
// "connected" : "disconnected"
String connectedFlags = iterator.next();
if (CONNECTED.equals(connectedFlags)) {
connected = true;
}
// slot, from-to [slot->-nodeID] [slot-<-nodeID]
List<String> slotStrings = LettuceLists.newList(iterator);
BitSet slots = readSlots(slotStrings);
RedisClusterNode partition = new RedisClusterNode(uri, nodeId, connected, replicaOf, pingSentTs, pongReceivedTs, configEpoch, slots, nodeFlags);
return partition;
}
use of io.lettuce.core.internal.HostAndPort in project lettuce-core by lettuce-io.
the class ClusterDistributionChannelWriterUnitTests method shouldParseIPv6MovedTargetCorrectly.
@Test
void shouldParseIPv6MovedTargetCorrectly() {
HostAndPort moveTarget = ClusterDistributionChannelWriter.getMoveTarget("MOVED 1234-2020 1:2:3:4::6:6381");
assertThat(moveTarget.getHostText()).isEqualTo("1:2:3:4::6");
assertThat(moveTarget.getPort()).isEqualTo(6381);
}
use of io.lettuce.core.internal.HostAndPort in project lettuce-core by lettuce-io.
the class ClusterDistributionChannelWriterUnitTests method shouldParseMovedTargetCorrectly.
@Test
void shouldParseMovedTargetCorrectly() {
HostAndPort moveTarget = ClusterDistributionChannelWriter.getMoveTarget("MOVED 1234-2020 127.0.0.1:6381");
assertThat(moveTarget.getHostText()).isEqualTo("127.0.0.1");
assertThat(moveTarget.getPort()).isEqualTo(6381);
}
Aggregations