use of org.redisson.RedissonShutdownException in project redisson by redisson.
the class CommandAsyncService method handleBlockingOperations.
private <R, V> void handleBlockingOperations(final AsyncDetails<V, R> details, final RedisConnection connection, Long popTimeout) {
final FutureListener<Boolean> listener = new FutureListener<Boolean>() {
@Override
public void operationComplete(Future<Boolean> future) throws Exception {
details.getMainPromise().tryFailure(new RedissonShutdownException("Redisson is shutdown"));
}
};
final AtomicBoolean canceledByScheduler = new AtomicBoolean();
final Timeout scheduledFuture;
if (popTimeout != 0) {
// to handle cases when connection has been lost
final Channel orignalChannel = connection.getChannel();
scheduledFuture = connectionManager.newTimeout(new TimerTask() {
@Override
public void run(Timeout timeout) throws Exception {
// and connection is still active
if (orignalChannel == connection.getChannel() && connection.isActive()) {
return;
}
canceledByScheduler.set(true);
details.getAttemptPromise().trySuccess(null);
}
}, popTimeout, TimeUnit.SECONDS);
} else {
scheduledFuture = null;
}
details.getMainPromise().addListener(new FutureListener<R>() {
@Override
public void operationComplete(Future<R> future) throws Exception {
if (scheduledFuture != null) {
scheduledFuture.cancel();
}
synchronized (listener) {
connectionManager.getShutdownPromise().removeListener(listener);
}
// handling cancel operation for commands from skipTimeout collection
if ((future.isCancelled() && details.getAttemptPromise().cancel(true)) || canceledByScheduler.get()) {
connection.forceFastReconnectAsync();
return;
}
if (future.cause() instanceof RedissonShutdownException) {
details.getAttemptPromise().tryFailure(future.cause());
}
}
});
synchronized (listener) {
if (!details.getMainPromise().isDone()) {
connectionManager.getShutdownPromise().addListener(listener);
}
}
}
use of org.redisson.RedissonShutdownException in project redisson by redisson.
the class RedisConnection method async.
public <T, R> RFuture<R> async(long timeout, Codec encoder, RedisCommand<T> command, Object... params) {
CompletableFuture<R> promise = new CompletableFuture<>();
if (timeout == -1) {
timeout = redisClient.getCommandTimeout();
}
if (redisClient.getEventLoopGroup().isShuttingDown()) {
RedissonShutdownException cause = new RedissonShutdownException("Redisson is shutdown");
return RedissonPromise.newFailedFuture(cause);
}
Timeout scheduledFuture = redisClient.getTimer().newTimeout(t -> {
RedisTimeoutException ex = new RedisTimeoutException("Command execution timeout for command: " + LogHelper.toString(command, params) + ", Redis client: " + redisClient);
promise.completeExceptionally(ex);
}, timeout, TimeUnit.MILLISECONDS);
promise.whenComplete((res, e) -> {
scheduledFuture.cancel();
});
ChannelFuture writeFuture = send(new CommandData<>(promise, encoder, command, params));
writeFuture.addListener((ChannelFutureListener) future -> {
if (!future.isSuccess()) {
promise.completeExceptionally(future.cause());
}
});
return new CompletableFutureWrapper<>(promise);
}
use of org.redisson.RedissonShutdownException in project redisson by redisson.
the class RedisExecutor method handleBlockingOperations.
private void handleBlockingOperations(CompletableFuture<R> attemptPromise, RedisConnection connection, Long popTimeout) {
FutureListener<Void> listener = f -> {
mainPromise.completeExceptionally(new RedissonShutdownException("Redisson is shutdown"));
};
Timeout scheduledFuture;
if (popTimeout != 0) {
// handling cases when connection has been lost
scheduledFuture = connectionManager.newTimeout(timeout -> {
if (attemptPromise.complete(null)) {
connection.forceFastReconnectAsync();
}
}, popTimeout + 1, TimeUnit.SECONDS);
} else {
scheduledFuture = null;
}
mainPromise.whenComplete((res, e) -> {
if (scheduledFuture != null) {
scheduledFuture.cancel();
}
synchronized (listener) {
connectionManager.getShutdownPromise().removeListener(listener);
}
// handling cancel operation for blocking commands
if ((mainPromise.isCancelled() || e instanceof InterruptedException) && !attemptPromise.isDone()) {
log.debug("Canceled blocking operation {} used {}", command, connection);
connection.forceFastReconnectAsync().whenComplete((r, ex) -> {
attemptPromise.cancel(true);
});
return;
}
if (e instanceof RedissonShutdownException) {
attemptPromise.completeExceptionally(e);
}
});
synchronized (listener) {
if (!mainPromise.isDone()) {
connectionManager.getShutdownPromise().addListener(listener);
}
}
}
use of org.redisson.RedissonShutdownException in project redisson by redisson.
the class RedissonExecutorRemoteService method invokeMethod.
@Override
protected <T> void invokeMethod(RemoteServiceRequest request, RemoteServiceMethod method, CompletableFuture<RemoteServiceCancelRequest> cancelRequestFuture, CompletableFuture<RRemoteServiceResponse> responsePromise) {
startedListeners.forEach(l -> l.onStarted(request.getId()));
if (taskTimeout > 0) {
commandExecutor.getConnectionManager().getGroup().schedule(() -> {
cancelRequestFuture.complete(new RemoteServiceCancelRequest(true, false));
}, taskTimeout, TimeUnit.MILLISECONDS);
}
try {
Object result = method.getMethod().invoke(method.getBean(), request.getArgs());
RemoteServiceResponse response = new RemoteServiceResponse(request.getId(), result);
responsePromise.complete(response);
} catch (Exception e) {
if (e instanceof InvocationTargetException && e.getCause() instanceof RedissonShutdownException) {
if (cancelRequestFuture != null) {
cancelRequestFuture.cancel(false);
}
return;
}
RemoteServiceResponse response = new RemoteServiceResponse(request.getId(), e.getCause());
responsePromise.complete(response);
log.error("Can't execute: " + request, e);
}
if (cancelRequestFuture != null) {
cancelRequestFuture.cancel(false);
}
if (commandExecutor.getNow(responsePromise) instanceof RemoteServiceResponse) {
RemoteServiceResponse response = (RemoteServiceResponse) commandExecutor.getNow(responsePromise);
if (response.getError() == null) {
successListeners.forEach(l -> l.onSucceeded(request.getId(), response.getResult()));
} else {
failureListeners.forEach(l -> l.onFailed(request.getId(), response.getError()));
}
} else {
failureListeners.forEach(l -> l.onFailed(request.getId(), null));
}
finishedListeners.forEach(l -> l.onFinished(request.getId()));
}
use of org.redisson.RedissonShutdownException 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);
}
});
}
Aggregations