use of org.redisson.client.protocol.CommandData in project redisson by redisson.
the class CommandDecoder method decode.
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
QueueCommand data = ctx.channel().attr(CommandsQueue.CURRENT_COMMAND).get();
if (log.isTraceEnabled()) {
log.trace("channel: {} message: {}", ctx.channel(), in.toString(0, in.writerIndex(), CharsetUtil.UTF_8));
}
if (state() == null) {
boolean makeCheckpoint = data != null;
if (data != null) {
if (data instanceof CommandsData) {
makeCheckpoint = false;
} else {
CommandData<Object, Object> cmd = (CommandData<Object, Object>) data;
if (cmd.getCommand().getReplayMultiDecoder() != null && (NestedMultiDecoder.class.isAssignableFrom(cmd.getCommand().getReplayMultiDecoder().getClass()) || SlotsDecoder.class.isAssignableFrom(cmd.getCommand().getReplayMultiDecoder().getClass()) || ListMultiDecoder.class.isAssignableFrom(cmd.getCommand().getReplayMultiDecoder().getClass()))) {
makeCheckpoint = false;
}
}
}
state(new State(makeCheckpoint));
}
state().setDecoderState(null);
if (data == null) {
decode(in, null, null, ctx.channel());
} else if (data instanceof CommandData) {
CommandData<Object, Object> cmd = (CommandData<Object, Object>) data;
try {
if (state().getLevels().size() > 0) {
decodeFromCheckpoint(ctx, in, data, cmd);
} else {
decode(in, cmd, null, ctx.channel());
}
} catch (Exception e) {
cmd.tryFailure(e);
}
} else if (data instanceof CommandsData) {
CommandsData commands = (CommandsData) data;
try {
decodeCommandBatch(ctx, in, data, commands);
} catch (Exception e) {
commands.getPromise().tryFailure(e);
}
return;
}
ctx.pipeline().get(CommandsQueue.class).sendNextCommand(ctx.channel());
state(null);
}
use of org.redisson.client.protocol.CommandData in project redisson by redisson.
the class CommandsQueue method sendData.
private void sendData(Channel ch) {
QueueCommandHolder command = queue.peek();
if (command != null && command.trySend()) {
QueueCommand data = command.getCommand();
List<CommandData<Object, Object>> pubSubOps = data.getPubSubOperations();
if (!pubSubOps.isEmpty()) {
for (CommandData<Object, Object> cd : pubSubOps) {
for (Object channel : cd.getParams()) {
ch.pipeline().get(CommandDecoder.class).addPubSubCommand(channel.toString(), cd);
}
}
} else {
ch.attr(CURRENT_COMMAND).set(data);
}
command.getChannelPromise().addListener(listener);
ch.writeAndFlush(data, command.getChannelPromise());
}
}
use of org.redisson.client.protocol.CommandData in project redisson by redisson.
the class RedisCommonBatchExecutor method sendCommand.
private void sendCommand(RedisConnection connection, CompletableFuture<Void> attemptPromise, List<CommandData<?, ?>> list) {
boolean isAtomic = options.getExecutionMode() != ExecutionMode.IN_MEMORY;
boolean isQueued = options.getExecutionMode() == ExecutionMode.REDIS_READ_ATOMIC || options.getExecutionMode() == ExecutionMode.REDIS_WRITE_ATOMIC;
CommandData<?, ?> lastCommand = connection.getLastCommand();
if (lastCommand != null && options.isSkipResult()) {
writeFuture = connection.getChannel().newPromise();
lastCommand.getPromise().whenComplete((r, e) -> {
CommandData<?, ?> currentLastCommand = connection.getLastCommand();
if (lastCommand != currentLastCommand && currentLastCommand != null) {
sendCommand(connection, attemptPromise, list);
return;
}
ChannelFuture wf = connection.send(new CommandsData(attemptPromise, list, options.isSkipResult(), isAtomic, isQueued, options.getSyncSlaves() > 0));
wf.addListener((ChannelFutureListener) future -> {
if (future.isSuccess()) {
((ChannelPromise) writeFuture).trySuccess(future.getNow());
} else {
((ChannelPromise) writeFuture).tryFailure(future.cause());
}
});
});
return;
}
writeFuture = connection.send(new CommandsData(attemptPromise, list, options.isSkipResult(), isAtomic, isQueued, options.getSyncSlaves() > 0));
}
use of org.redisson.client.protocol.CommandData in project redisson by redisson.
the class CommandAsyncService method async.
protected <V, R> void async(final boolean readOnlyMode, final NodeSource source, final Codec codec, final RedisCommand<V> command, final Object[] params, final RPromise<R> mainPromise, final int attempt) {
if (mainPromise.isCancelled()) {
return;
}
if (!connectionManager.getShutdownLatch().acquire()) {
mainPromise.tryFailure(new RedissonShutdownException("Redisson is shutdown"));
return;
}
final AsyncDetails<V, R> details = AsyncDetails.acquire();
if (isRedissonReferenceSupportEnabled()) {
try {
for (int i = 0; i < params.length; i++) {
RedissonReference reference = redisson != null ? RedissonObjectFactory.toReference(redisson, params[i]) : RedissonObjectFactory.toReference(redissonReactive, params[i]);
params[i] = reference == null ? params[i] : reference;
}
} catch (Exception e) {
connectionManager.getShutdownLatch().release();
mainPromise.tryFailure(e);
return;
}
}
final RFuture<RedisConnection> connectionFuture;
if (readOnlyMode) {
connectionFuture = connectionManager.connectionReadOp(source, command);
} else {
connectionFuture = connectionManager.connectionWriteOp(source, command);
}
final RPromise<R> attemptPromise = connectionManager.newPromise();
details.init(connectionFuture, attemptPromise, readOnlyMode, source, codec, command, params, mainPromise, attempt);
final TimerTask retryTimerTask = new TimerTask() {
@Override
public void run(Timeout t) throws Exception {
if (details.getAttemptPromise().isDone()) {
return;
}
if (details.getConnectionFuture().cancel(false)) {
connectionManager.getShutdownLatch().release();
} else {
if (details.getConnectionFuture().isSuccess()) {
ChannelFuture writeFuture = details.getWriteFuture();
if (writeFuture != null && !writeFuture.cancel(false) && writeFuture.isSuccess()) {
return;
}
}
}
if (details.getMainPromise().isCancelled()) {
if (details.getAttemptPromise().cancel(false)) {
AsyncDetails.release(details);
}
return;
}
if (details.getAttempt() == connectionManager.getConfig().getRetryAttempts()) {
if (details.getException() == null) {
details.setException(new RedisTimeoutException("Command execution timeout for command: " + command + " with params: " + LogHelper.toString(details.getParams())));
}
details.getAttemptPromise().tryFailure(details.getException());
return;
}
if (!details.getAttemptPromise().cancel(false)) {
return;
}
int count = details.getAttempt() + 1;
if (log.isDebugEnabled()) {
log.debug("attempt {} for command {} and params {}", count, details.getCommand(), Arrays.toString(details.getParams()));
}
async(details.isReadOnlyMode(), details.getSource(), details.getCodec(), details.getCommand(), details.getParams(), details.getMainPromise(), count);
AsyncDetails.release(details);
}
};
Timeout timeout = connectionManager.newTimeout(retryTimerTask, connectionManager.getConfig().getRetryInterval(), TimeUnit.MILLISECONDS);
details.setTimeout(timeout);
connectionFuture.addListener(new FutureListener<RedisConnection>() {
@Override
public void operationComplete(Future<RedisConnection> connFuture) throws Exception {
if (connFuture.isCancelled()) {
return;
}
if (!connFuture.isSuccess()) {
connectionManager.getShutdownLatch().release();
details.setException(convertException(connectionFuture));
return;
}
if (details.getAttemptPromise().isDone() || details.getMainPromise().isDone()) {
releaseConnection(source, connectionFuture, details.isReadOnlyMode(), details.getAttemptPromise(), details);
return;
}
final RedisConnection connection = connFuture.getNow();
if (details.getSource().getRedirect() == Redirect.ASK) {
List<CommandData<?, ?>> list = new ArrayList<CommandData<?, ?>>(2);
RPromise<Void> promise = connectionManager.newPromise();
list.add(new CommandData<Void, Void>(promise, details.getCodec(), RedisCommands.ASKING, new Object[] {}));
list.add(new CommandData<V, R>(details.getAttemptPromise(), details.getCodec(), details.getCommand(), details.getParams()));
RPromise<Void> main = connectionManager.newPromise();
ChannelFuture future = connection.send(new CommandsData(main, list));
details.setWriteFuture(future);
} else {
if (log.isDebugEnabled()) {
log.debug("aquired connection for command {} and params {} from slot {} using node {}", details.getCommand(), Arrays.toString(details.getParams()), details.getSource(), connection.getRedisClient().getAddr());
}
ChannelFuture future = connection.send(new CommandData<V, R>(details.getAttemptPromise(), details.getCodec(), details.getCommand(), details.getParams()));
details.setWriteFuture(future);
}
details.getWriteFuture().addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
checkWriteFuture(details, connection);
}
});
releaseConnection(source, connectionFuture, details.isReadOnlyMode(), details.getAttemptPromise(), details);
}
});
attemptPromise.addListener(new FutureListener<R>() {
@Override
public void operationComplete(Future<R> future) throws Exception {
checkAttemptFuture(source, details, future);
}
});
}
use of org.redisson.client.protocol.CommandData in project redisson by redisson.
the class CommandBatchService method checkConnectionFuture.
private void checkConnectionFuture(final Entry entry, final NodeSource source, final RPromise<Void> mainPromise, final RPromise<Void> attemptPromise, final AsyncDetails details, RFuture<RedisConnection> connFuture, final boolean noResult) {
if (attemptPromise.isDone() || mainPromise.isCancelled() || connFuture.isCancelled()) {
return;
}
if (!connFuture.isSuccess()) {
connectionManager.getShutdownLatch().release();
details.setException(convertException(connFuture));
return;
}
final RedisConnection connection = connFuture.getNow();
List<CommandData<?, ?>> list = new ArrayList<CommandData<?, ?>>(entry.getCommands().size() + 1);
if (source.getRedirect() == Redirect.ASK) {
RPromise<Void> promise = connectionManager.newPromise();
list.add(new CommandData<Void, Void>(promise, StringCodec.INSTANCE, RedisCommands.ASKING, new Object[] {}));
}
for (BatchCommandData<?, ?> c : entry.getCommands()) {
if (c.getPromise().isSuccess()) {
// skip successful commands
continue;
}
list.add(c);
}
ChannelFuture future = connection.send(new CommandsData(attemptPromise, list, noResult));
details.setWriteFuture(future);
details.getWriteFuture().addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
checkWriteFuture(attemptPromise, details, connection, future, noResult);
}
});
releaseConnection(source, connFuture, entry.isReadOnlyMode(), attemptPromise, details);
}
Aggregations