use of io.lettuce.core.RedisChannelWriter in project lettuce-core by lettuce-io.
the class AtLeastOnceTest method commandRetriedChannelClosesWhileFlush.
@Test
void commandRetriedChannelClosesWhileFlush() {
assumeTrue(Version.identify().get("netty-transport").artifactVersion().startsWith("4.0.2"));
StatefulRedisConnection<String, String> connection = client.connect();
RedisCommands<String, String> sync = connection.sync();
RedisCommands<String, String> verificationConnection = client.connect().sync();
RedisChannelWriter channelWriter = ConnectionTestUtil.getChannelWriter(connection);
sync.set(key, "1");
assertThat(verificationConnection.get(key)).isEqualTo("1");
final CountDownLatch block = new CountDownLatch(1);
ConnectionWatchdog connectionWatchdog = ConnectionTestUtil.getConnectionWatchdog(sync.getStatefulConnection());
AsyncCommand<String, String, Object> command = getBlockOnEncodeCommand(block);
channelWriter.write(command);
connectionWatchdog.setReconnectSuspended(true);
Channel channel = ConnectionTestUtil.getChannel(sync.getStatefulConnection());
channel.unsafe().disconnect(channel.newPromise());
assertThat(channel.isOpen()).isFalse();
assertThat(command.isCancelled()).isFalse();
assertThat(command.isDone()).isFalse();
block.countDown();
assertThat(command.await(2, TimeUnit.SECONDS)).isFalse();
connectionWatchdog.setReconnectSuspended(false);
connectionWatchdog.scheduleReconnect();
assertThat(command.await(2, TimeUnit.SECONDS)).isTrue();
assertThat(command.isCancelled()).isFalse();
assertThat(command.isDone()).isTrue();
assertThat(verificationConnection.get(key)).isEqualTo("2");
assertThat(ConnectionTestUtil.getStack(sync.getStatefulConnection())).isEmpty();
assertThat(ConnectionTestUtil.getCommandBuffer(sync.getStatefulConnection())).isEmpty();
sync.getStatefulConnection().close();
verificationConnection.getStatefulConnection().close();
}
use of io.lettuce.core.RedisChannelWriter in project lettuce-core by lettuce-io.
the class AtLeastOnceTest method commandFailsWhenFailOnEncode.
@Test
void commandFailsWhenFailOnEncode() {
RedisCommands<String, String> connection = client.connect().sync();
RedisChannelWriter channelWriter = ConnectionTestUtil.getChannelWriter(connection.getStatefulConnection());
RedisCommands<String, String> verificationConnection = client.connect().sync();
connection.set(key, "1");
AsyncCommand<String, String, String> working = new AsyncCommand<>(new Command<>(CommandType.INCR, new IntegerOutput(StringCodec.UTF8), new CommandArgs<>(StringCodec.UTF8).addKey(key)));
channelWriter.write(working);
assertThat(working.await(2, TimeUnit.SECONDS)).isTrue();
assertThat(connection.get(key)).isEqualTo("2");
AsyncCommand<String, String, Object> command = new AsyncCommand(new Command<>(CommandType.INCR, new IntegerOutput(StringCodec.UTF8), new CommandArgs<>(StringCodec.UTF8).addKey(key))) {
@Override
public void encode(ByteBuf buf) {
throw new IllegalStateException("I want to break free");
}
};
channelWriter.write(command);
assertThat(command.await(2, TimeUnit.SECONDS)).isTrue();
assertThat(command.isCancelled()).isFalse();
assertThat(getException(command)).isInstanceOf(EncoderException.class);
assertThat(verificationConnection.get(key)).isEqualTo("2");
assertThat(ConnectionTestUtil.getStack(connection.getStatefulConnection())).isNotEmpty();
connection.getStatefulConnection().close();
}
use of io.lettuce.core.RedisChannelWriter in project lettuce-core by lettuce-io.
the class AtMostOnceTest method commandFailsDuringDecode.
@Test
void commandFailsDuringDecode() {
StatefulRedisConnection<String, String> connection = client.connect();
RedisCommands<String, String> sync = connection.sync();
RedisChannelWriter channelWriter = ConnectionTestUtil.getChannelWriter(connection);
RedisCommands<String, String> verificationConnection = client.connect().sync();
sync.set(key, "1");
AsyncCommand<String, String, String> command = new AsyncCommand<>(new Command<>(CommandType.INCR, new StatusOutput<>(StringCodec.UTF8), new CommandArgs<>(StringCodec.UTF8).addKey(key)));
channelWriter.write(command);
assertThat(command.await(2, TimeUnit.SECONDS)).isTrue();
assertThat(command.isCancelled()).isFalse();
assertThat(getException(command)).isInstanceOf(UnsupportedOperationException.class);
assertThat(verificationConnection.get(key)).isEqualTo("2");
assertThat(sync.get(key)).isEqualTo("2");
connection.close();
}
use of io.lettuce.core.RedisChannelWriter in project lettuce-core by lettuce-io.
the class ClusterDistributionChannelWriter method write.
@SuppressWarnings("unchecked")
@Override
public <K, V> Collection<RedisCommand<K, V, ?>> write(Collection<? extends RedisCommand<K, V, ?>> commands) {
LettuceAssert.notNull(commands, "Commands must not be null");
if (closed) {
commands.forEach(it -> it.completeExceptionally(new RedisException("Connection is closed")));
return (Collection<RedisCommand<K, V, ?>>) commands;
}
List<ClusterCommand<K, V, ?>> clusterCommands = new ArrayList<>(commands.size());
List<ClusterCommand<K, V, ?>> defaultCommands = new ArrayList<>(commands.size());
Map<SlotIntent, List<ClusterCommand<K, V, ?>>> partitions = new HashMap<>();
// TODO: Retain order or retain Intent preference?
// Currently: Retain order
Intent intent = getIntent(commands);
for (RedisCommand<K, V, ?> cmd : commands) {
if (cmd instanceof ClusterCommand) {
clusterCommands.add((ClusterCommand) cmd);
continue;
}
CommandArgs<K, V> args = cmd.getArgs();
ByteBuffer firstEncodedKey = args != null ? args.getFirstEncodedKey() : null;
if (firstEncodedKey == null) {
defaultCommands.add(new ClusterCommand<>(cmd, this, executionLimit));
continue;
}
int hash = getSlot(args.getFirstEncodedKey());
List<ClusterCommand<K, V, ?>> commandPartition = partitions.computeIfAbsent(SlotIntent.of(intent, hash), slotIntent -> new ArrayList<>());
commandPartition.add(new ClusterCommand<>(cmd, this, executionLimit));
}
for (Map.Entry<SlotIntent, List<ClusterCommand<K, V, ?>>> entry : partitions.entrySet()) {
SlotIntent slotIntent = entry.getKey();
RedisChannelHandler<K, V> connection = (RedisChannelHandler<K, V>) clusterConnectionProvider.getConnection(slotIntent.intent, slotIntent.slotHash);
RedisChannelWriter channelWriter = connection.getChannelWriter();
if (channelWriter instanceof ClusterDistributionChannelWriter) {
ClusterDistributionChannelWriter writer = (ClusterDistributionChannelWriter) channelWriter;
channelWriter = writer.defaultWriter;
}
if (channelWriter != null && channelWriter != this && channelWriter != defaultWriter) {
channelWriter.write(entry.getValue());
}
}
clusterCommands.forEach(this::write);
defaultCommands.forEach(defaultWriter::write);
return (Collection) commands;
}
use of io.lettuce.core.RedisChannelWriter in project lettuce-core by lettuce-io.
the class AtLeastOnceTest method commandFailsDuringDecode.
@Test
void commandFailsDuringDecode() {
RedisCommands<String, String> connection = client.connect().sync();
RedisChannelWriter channelWriter = ConnectionTestUtil.getChannelWriter(connection.getStatefulConnection());
RedisCommands<String, String> verificationConnection = client.connect().sync();
connection.set(key, "1");
AsyncCommand<String, String, String> command = new AsyncCommand(new Command<>(CommandType.INCR, new StatusOutput<>(StringCodec.UTF8), new CommandArgs<>(StringCodec.UTF8).addKey(key)));
channelWriter.write(command);
assertThat(command.await(2, TimeUnit.SECONDS)).isTrue();
assertThat(command.isCancelled()).isFalse();
assertThat(command.isDone()).isTrue();
assertThat(getException(command)).isInstanceOf(UnsupportedOperationException.class);
assertThat(verificationConnection.get(key)).isEqualTo("2");
assertThat(connection.get(key)).isEqualTo("2");
connection.getStatefulConnection().close();
verificationConnection.getStatefulConnection().close();
}
Aggregations