use of org.redisson.misc.RPromise in project redisson by redisson.
the class RedisConnection method await.
public <R> R await(RFuture<R> future) {
final CountDownLatch l = new CountDownLatch(1);
future.addListener(new FutureListener<R>() {
@Override
public void operationComplete(Future<R> future) throws Exception {
l.countDown();
}
});
try {
if (!l.await(redisClient.getCommandTimeout(), TimeUnit.MILLISECONDS)) {
RPromise<R> promise = (RPromise<R>) future;
RedisTimeoutException ex = new RedisTimeoutException("Command execution timeout for " + redisClient.getAddr());
promise.tryFailure(ex);
throw ex;
}
if (!future.isSuccess()) {
if (future.cause() instanceof RedisException) {
throw (RedisException) future.cause();
}
throw new RedisException("Unexpected exception while processing command", future.cause());
}
return future.getNow();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return null;
}
}
use of org.redisson.misc.RPromise in project redisson by redisson.
the class RedissonTransferQueue method tryTransferAsync.
public RFuture<Boolean> tryTransferAsync(V v, long timeout, TimeUnit unit) {
RPromise<Boolean> result = new RedissonPromise<>();
result.setUncancellable();
RemotePromise<Void> future = (RemotePromise<Void>) service.invoke(v).toCompletableFuture();
long remainTime = unit.toMillis(timeout);
long startTime = System.currentTimeMillis();
Timeout timeoutFuture = commandExecutor.getConnectionManager().newTimeout(tt -> {
if (!future.getAddFuture().cancel(false)) {
future.cancelAsync(false);
}
}, remainTime, TimeUnit.MILLISECONDS);
future.whenComplete((res, exc) -> {
if (future.isCancelled()) {
result.trySuccess(false);
return;
}
timeoutFuture.cancel();
if (exc != null) {
result.tryFailure(exc);
return;
}
result.trySuccess(true);
});
future.getAddFuture().whenComplete((added, e) -> {
if (future.getAddFuture().isCancelled()) {
result.trySuccess(false);
return;
}
if (e != null) {
timeoutFuture.cancel();
result.tryFailure(e);
return;
}
if (!added) {
timeoutFuture.cancel();
result.trySuccess(false);
return;
}
Runnable task = () -> {
future.cancelAsync(false).whenComplete((canceled, ex) -> {
if (ex != null) {
timeoutFuture.cancel();
result.tryFailure(ex);
return;
}
if (canceled) {
timeoutFuture.cancel();
result.trySuccess(false);
}
});
};
long time = remainTime - (System.currentTimeMillis() - startTime);
if (time > 0) {
commandExecutor.getConnectionManager().newTimeout(tt -> {
task.run();
}, time, TimeUnit.MILLISECONDS);
} else {
task.run();
}
});
return result;
}
use of org.redisson.misc.RPromise in project redisson by redisson.
the class CommandBatchService method executeRedisBasedQueue.
private <R> RFuture<R> executeRedisBasedQueue() {
RPromise<R> resultPromise = new RedissonPromise<R>();
long responseTimeout;
if (options.getResponseTimeout() > 0) {
responseTimeout = options.getResponseTimeout();
} else {
responseTimeout = connectionManager.getConfig().getTimeout();
}
Timeout timeout = connectionManager.newTimeout(new TimerTask() {
@Override
public void run(Timeout timeout) throws Exception {
connections.values().forEach(c -> {
c.getCancelCallback().run();
});
resultPromise.tryFailure(new RedisTimeoutException("Response timeout for queued commands " + responseTimeout + ": " + commands.values().stream().flatMap(e -> e.getCommands().stream().map(d -> d.getCommand())).collect(Collectors.toList())));
}
}, responseTimeout, TimeUnit.MILLISECONDS);
CompletableFuture<Void> allFutures = CompletableFuture.allOf(commands.values().stream().flatMap(m -> m.getCommands().stream().map(c -> ((BatchPromise) c.getPromise()).getSentPromise())).toArray(CompletableFuture[]::new));
allFutures.whenComplete((fr, exc) -> {
if (!timeout.cancel()) {
return;
}
for (Entry entry : commands.values()) {
for (BatchCommandData<?, ?> command : entry.getCommands()) {
if (command.getPromise().isDone() && command.getPromise().isCompletedExceptionally()) {
resultPromise.tryFailure(cause(command.getPromise()));
break;
}
}
}
if (resultPromise.isDone()) {
return;
}
Map<MasterSlaveEntry, List<Object>> result = new ConcurrentHashMap<>();
List<CompletableFuture<Void>> futures = new ArrayList<>(commands.size());
for (Map.Entry<MasterSlaveEntry, Entry> entry : commands.entrySet()) {
RFuture<List<Object>> execPromise = async(entry.getValue().isReadOnlyMode(), new NodeSource(entry.getKey()), connectionManager.getCodec(), RedisCommands.EXEC, new Object[] {}, false, false);
CompletionStage<Void> f = execPromise.thenCompose(r -> {
BatchCommandData<?, Integer> lastCommand = (BatchCommandData<?, Integer>) entry.getValue().getCommands().peekLast();
result.put(entry.getKey(), r);
if (RedisCommands.WAIT.getName().equals(lastCommand.getCommand().getName())) {
return lastCommand.getPromise().thenApply(i -> null);
}
return CompletableFuture.completedFuture(null);
});
futures.add(f.toCompletableFuture());
}
CompletableFuture<Void> future = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
future.whenComplete((res, ex) -> {
executed.set(true);
if (ex != null) {
resultPromise.tryFailure(ex);
return;
}
try {
for (java.util.Map.Entry<MasterSlaveEntry, List<Object>> entry : result.entrySet()) {
Entry commandEntry = commands.get(entry.getKey());
Iterator<Object> resultIter = entry.getValue().iterator();
for (BatchCommandData<?, ?> data : commandEntry.getCommands()) {
if (data.getCommand().getName().equals(RedisCommands.EXEC.getName())) {
break;
}
CompletableFuture<Object> promise = (CompletableFuture<Object>) data.getPromise();
if (resultIter.hasNext()) {
promise.complete(resultIter.next());
} else {
// fix for https://github.com/redisson/redisson/issues/2212
promise.complete(null);
}
}
}
List<BatchCommandData> entries = new ArrayList<>();
for (Entry e : commands.values()) {
entries.addAll(e.getCommands());
}
Collections.sort(entries);
List<Object> responses = new ArrayList<>(entries.size());
int syncedSlaves = 0;
for (BatchCommandData<?, ?> commandEntry : entries) {
if (isWaitCommand(commandEntry)) {
syncedSlaves += (Integer) commandEntry.getPromise().getNow(null);
} else if (!commandEntry.getCommand().getName().equals(RedisCommands.MULTI.getName()) && !commandEntry.getCommand().getName().equals(RedisCommands.EXEC.getName())) {
Object entryResult = commandEntry.getPromise().getNow(null);
if (objectBuilder != null) {
entryResult = objectBuilder.tryHandleReference(entryResult, referenceType);
}
responses.add(entryResult);
}
}
BatchResult<Object> r = new BatchResult<>(responses, syncedSlaves);
resultPromise.trySuccess((R) r);
} catch (Exception e) {
resultPromise.tryFailure(e);
}
});
});
return resultPromise;
}
use of org.redisson.misc.RPromise in project redisson by redisson.
the class BaseTransactionalMap method addAndGetOperationAsync.
protected RFuture<V> addAndGetOperationAsync(K key, Number value) {
RPromise<V> result = new RedissonPromise<V>();
long threadId = Thread.currentThread().getId();
executeLocked(result, key, new Runnable() {
@Override
public void run() {
HashValue keyHash = toKeyHash(key);
MapEntry entry = state.get(keyHash);
if (entry != null) {
BigDecimal currentValue = BigDecimal.ZERO;
if (entry != MapEntry.NULL) {
currentValue = (BigDecimal) entry.getValue();
}
BigDecimal res = currentValue.add(new BigDecimal(value.toString()));
operations.add(new MapAddAndGetOperation(map, key, value, transactionId, threadId));
state.put(keyHash, new MapEntry(key, res));
if (deleted != null) {
deleted = false;
}
NumberConvertor convertor = new NumberConvertor(value.getClass());
result.trySuccess((V) convertor.convert(res.toPlainString()));
return;
}
map.getAsync(key).onComplete((r, e) -> {
if (e != null) {
result.tryFailure(e);
return;
}
BigDecimal currentValue = new BigDecimal(r.toString());
BigDecimal res = currentValue.add(new BigDecimal(value.toString()));
operations.add(new MapAddAndGetOperation(map, key, value, transactionId, threadId));
state.put(keyHash, new MapEntry(key, res));
if (deleted != null) {
deleted = false;
}
NumberConvertor convertor = new NumberConvertor(value.getClass());
result.trySuccess((V) convertor.convert(res.toPlainString()));
});
}
});
return result;
}
Aggregations