public static AsyncDetails acquire() { // AsyncDetails result = queue.poll(); // if (result != null) { // return result; // } AsyncDetails details = new AsyncDetails(); return details; }
@Override public void run(Timeout t) throws Exception { if (details.getAttemptPromise().isDone()) { return; if (details.getConnectionFuture().cancel(false)) { if (details.getException() == null) { details.setException(new RedisTimeoutException("Unable to get connection! " + "Node source: " + source + ", command: " + command + ", command params: " + LogHelper.toString(details.getParams()) + " after " + details.getAttempt() + " retry attempts")); if (details.getConnectionFuture().isSuccess()) { if (details.getWriteFuture() == null || !details.getWriteFuture().isDone()) { if (details.getAttempt() == connectionManager.getConfig().getRetryAttempts()) { if (details.getWriteFuture() != null && details.getWriteFuture().cancel(false)) { if (details.getException() == null) { details.setException(new RedisTimeoutException("Unable to send command! " + "Node source: " + source + ", connection: " + details.getConnectionFuture().getNow() + ", current command in queue: " + details.getConnectionFuture().getNow().getCurrentCommand() + ", command: " + command + ", command params: " + LogHelper.toString(details.getParams()) + " after " + connectionManager.getConfig().getRetryAttempts() + " retry attempts")); details.getAttemptPromise().tryFailure(details.getException()); details.incAttempt(); Timeout timeout = connectionManager.newTimeout(this, connectionManager.getConfig().getRetryInterval(), TimeUnit.MILLISECONDS); details.setTimeout(timeout); return;
@Override public void operationComplete(Future<Void> future) throws Exception { CommandBatchService.super.releaseConnection(details.getSource(), details.getConnectionFuture(), details.isReadOnlyMode(), details.getAttemptPromise(), details); } });
@Override public void run(Timeout timeout) throws Exception { async(details.isReadOnlyMode(), source, details.getCodec(), details.getCommand(), details.getParams(), details.getMainPromise(), details.getAttempt(), ignoreRedirect); } }, 1, TimeUnit.SECONDS);
@Override public void run(Timeout timeout) throws Exception { if (details.getAttempt() < connectionManager.getConfig().getRetryAttempts()) { if (!details.getAttemptPromise().cancel(false)) { return; } int count = details.getAttempt() + 1; if (log.isDebugEnabled()) { log.debug("attempt {} for command {} and params {}", count, details.getCommand(), LogHelper.toString(details.getParams())); } details.removeMainPromiseListener(); async(details.isReadOnlyMode(), details.getSource(), details.getCodec(), details.getCommand(), details.getParams(), details.getMainPromise(), count, ignoreRedirect); AsyncDetails.release(details); return; } details.getAttemptPromise().tryFailure( new RedisResponseTimeoutException("Redis server response timeout (" + timeoutAmount + " ms) occured" + " after " + connectionManager.getConfig().getRetryAttempts() + " retry attempts. Command: " + details.getCommand() + ", params: " + LogHelper.toString(details.getParams()) + ", channel: " + connection.getChannel())); } };
protected <R, V> void checkAttemptFuture(final NodeSource source, final AsyncDetails<V, R> details, Future<R> future, final boolean ignoreRedirect) { details.getTimeout().cancel(); if (future.isCancelled()) { return; details.removeMainPromiseListener(); details.getMainPromise().tryFailure(new RedisException("MOVED redirection loop detected. Node " + source.getAddr() + " has further redirect to " + ex.getUrl())); return; async(details.isReadOnlyMode(), new NodeSource(ex.getSlot(), ex.getUrl(), Redirect.MOVED), details.getCodec(), details.getCommand(), details.getParams(), details.getMainPromise(), details.getAttempt(), ignoreRedirect); AsyncDetails.release(details); return; async(details.isReadOnlyMode(), new NodeSource(ex.getSlot(), ex.getUrl(), Redirect.ASK), details.getCodec(), details.getCommand(), details.getParams(), details.getMainPromise(), details.getAttempt(), ignoreRedirect); AsyncDetails.release(details); return; async(details.isReadOnlyMode(), source, details.getCodec(), details.getCommand(), details.getParams(), details.getMainPromise(), details.getAttempt(), ignoreRedirect); AsyncDetails.release(details); return; AsyncDetails.release(details); return; free(details.getParams());
private <V, R> void checkWriteFuture(final AsyncDetails<V, R> details, final boolean ignoreRedirect, final RedisConnection connection) { ChannelFuture future = details.getWriteFuture(); if (future.isCancelled() || details.getAttemptPromise().isDone()) { return; details.setException(new WriteRedisConnectionException( "Unable to send command! Node source: " + details.getSource() + ", connection: " + connection + ", command: " + details.getCommand() + ", command params: " + LogHelper.toString(details.getParams()) + " after " + details.getAttempt() + " retry attempts", future.cause())); if (details.getAttempt() == connectionManager.getConfig().getRetryAttempts()) { if (!details.getAttemptPromise().tryFailure(details.getException())) { log.error(details.getException().getMessage()); details.getTimeout().cancel(); if (RedisCommands.BLOCKING_COMMAND_NAMES.contains(details.getCommand().getName()) || RedisCommands.BLOCKING_COMMANDS.contains(details.getCommand())) { Long popTimeout = null; if (RedisCommands.BLOCKING_COMMANDS.contains(details.getCommand())) { boolean found = false; for (Object param : details.getParams()) { if (found) { popTimeout = Long.valueOf(param.toString()) / 1000; popTimeout = Long.valueOf(details.getParams()[details.getParams().length - 1].toString()); details.setTimeout(timeout);
protected <R, V> void sendCommand(final AsyncDetails<V, R> details, final RedisConnection connection) { if (details.getSource().getRedirect() == Redirect.ASK) { List<CommandData<?, ?>> list = new ArrayList<CommandData<?, ?>>(2); RPromise<Void> promise = new RedissonPromise<Void>(); 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 = new RedissonPromise<Void>(); ChannelFuture future = connection.send(new CommandsData(main, list, false)); details.setWriteFuture(future); } else { if (log.isDebugEnabled()) { log.debug("acquired connection for command {} and params {} from slot {} using node {}... {}", details.getCommand(), LogHelper.toString(details.getParams()), details.getSource(), connection.getRedisClient().getAddr(), connection); } ChannelFuture future = connection.send(new CommandData<V, R>(details.getAttemptPromise(), details.getCodec(), details.getCommand(), details.getParams())); details.setWriteFuture(future); } }
@Override public void run(Timeout timeout) throws Exception { if (details.getAttempt() < connectionManager.getConfig().getRetryAttempts()) { if (!details.getAttemptPromise().cancel(false)) { return; } int count = details.getAttempt() + 1; if (log.isDebugEnabled()) { log.debug("attempt {} for command {} and params {}", count, details.getCommand(), LogHelper.toString(details.getParams())); } details.removeMainPromiseListener(); execute(entry, details.getSource(), mainPromise, slots, count, options); return; } attemptPromise.tryFailure( new RedisResponseTimeoutException("Redis server response timeout during command batch execution. Channel: " + connection.getChannel())); } };
if (details.getException() == null) { details.setException(new RedisTimeoutException("Unable to get connection! " + "Node source: " + source + " after " + attempts + " retry attempts")); if (details.getWriteFuture() == null || !details.getWriteFuture().isDone()) { if (details.getAttempt() == attempts) { if (details.getWriteFuture() != null && details.getWriteFuture().cancel(false)) { if (details.getException() == null) { details.setException(new RedisTimeoutException("Unable to send batch after " + attempts + " retry attempts")); attemptPromise.tryFailure(details.getException()); details.incAttempt(); Timeout timeout = connectionManager.newTimeout(this, interval, TimeUnit.MILLISECONDS); details.setTimeout(timeout); return; if (details.getWriteFuture().isDone() && details.getWriteFuture().isSuccess()) { return; if (details.getException() == null) { details.setException(new RedisTimeoutException("Batch command execution timeout")); attemptPromise.tryFailure(details.getException()); return;
@Override public void operationComplete(Future<RedisConnection> connFuture) throws Exception { if (connFuture.isCancelled()) { connectionManager.getShutdownLatch().release(); 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(); sendCommand(details, connection); details.getWriteFuture().addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { checkWriteFuture(details, ignoreRedirect, connection); } }); releaseConnection(source, connectionFuture, details.isReadOnlyMode(), details.getAttemptPromise(), details); } });
details.setException(new WriteRedisConnectionException("Can't write command batch to channel: " + future.channel(), future.cause())); if (details.getAttempt() == attempts) { if (!attemptPromise.tryFailure(details.getException())) { log.error(details.getException().getMessage()); details.getTimeout().cancel(); details.setTimeout(timeoutTask);
final AsyncDetails<V, R> details = AsyncDetails.acquire(); final RFuture<RedisConnection> connectionFuture = getConnection(readOnlyMode, source, command); details.init(connectionFuture, attemptPromise, readOnlyMode, source, codecToUse, command, params, mainPromise, attempt); details.setTimeout(timeout); details.setupMainPromiseListener(mainPromiseListener);
@Override public void operationComplete(Future<R> future) throws Exception { if (!connectionFuture.isSuccess()) { return; } RedisConnection connection = connectionFuture.getNow(); connectionManager.getShutdownLatch().release(); if (isReadOnly) { connectionManager.releaseRead(source, connection); } else { connectionManager.releaseWrite(source, connection); } if (log.isDebugEnabled()) { log.debug("connection released for command {} and params {} from slot {} using connection {}", details.getCommand(), LogHelper.toString(details.getParams()), details.getSource(), connection); } } });
final AsyncDetails details = new AsyncDetails(); details.init(null, attemptPromise, entry.isReadOnlyMode(), source, null, null, null, mainPromise, attempt); details.setTimeout(timeout); mainPromise.addListener(mainPromiseListener);
@Override public void operationComplete(Future<R> future) throws Exception { if (future.isCancelled() && connectionFuture.cancel(false)) { log.debug("Connection obtaining canceled for {}", command); details.getTimeout().cancel(); if (details.getAttemptPromise().cancel(false)) { free(params); } } } };
@Override public void operationComplete(Future<R> future) throws Exception { if (scheduledFuture != null) { scheduledFuture.cancel(); } synchronized (listener) { connectionManager.getShutdownPromise().removeListener(listener); } // handling cancel operation for blocking commands if (future.isCancelled() && !details.getAttemptPromise().isDone()) { log.debug("Canceled blocking operation {} used {}", details.getCommand(), connection); connection.forceFastReconnectAsync().addListener(new FutureListener<Void>() { @Override public void operationComplete(Future<Void> future) throws Exception { details.getAttemptPromise().cancel(true); } }); return; } if (future.cause() instanceof RedissonShutdownException) { details.getAttemptPromise().tryFailure(future.cause()); } } });
@Override public void operationComplete(Future<Void> future) throws Exception { details.getTimeout().cancel(); if (future.isCancelled()) { return; if (details.getAttempt() < connectionManager.getConfig().getRetryAttempts()) { entry.clearErrors(); connectionManager.newTimeout(new TimerTask() {
@Override public void operationComplete(Future<Boolean> future) throws Exception { details.getMainPromise().tryFailure(new RedissonShutdownException("Redisson is shutdown")); } };
@Override protected <V, R> void handleError(final AsyncDetails<V, R> details, RPromise<R> promise, Throwable cause) { if (isRedisBasedQueue() && promise instanceof BatchPromise) { BatchPromise<R> batchPromise = (BatchPromise<R>) promise; RPromise<R> sentPromise = (RPromise<R>) batchPromise.getSentPromise(); sentPromise.tryFailure(cause); promise.tryFailure(cause); if (executed.compareAndSet(false, true)) { details.getConnectionFuture().getNow().forceFastReconnectAsync().addListener(new FutureListener<Void>() { @Override public void operationComplete(Future<Void> future) throws Exception { CommandBatchService.super.releaseConnection(details.getSource(), details.getConnectionFuture(), details.isReadOnlyMode(), details.getAttemptPromise(), details); } }); } semaphore.release(); return; } super.handleError(details, promise, cause); }