use of org.redisson.api.RFuture in project redisson by redisson.
the class RedissonBlockingFairQueue method tryPollLastAndOfferFirstToAsync.
private void tryPollLastAndOfferFirstToAsync(final long startTime, final long timeout, final TimeUnit unit, final RFuture<RedissonLockEntry> subscribeFuture, final RPromise<V> promise, final String queueName) {
if (promise.isDone()) {
unsubscribe(subscribeFuture);
return;
}
long spentTime = System.currentTimeMillis() - startTime;
long remainTime = unit.toMillis(timeout) - spentTime;
if (remainTime <= 0) {
unsubscribe(subscribeFuture);
promise.trySuccess(null);
return;
}
RFuture<Long> tryAcquireFuture = tryAcquireAsync();
tryAcquireFuture.addListener(new FutureListener<Long>() {
@Override
public void operationComplete(Future<Long> future) throws Exception {
if (!future.isSuccess()) {
unsubscribe(subscribeFuture);
promise.tryFailure(future.cause());
return;
}
Long currentTimeout = future.getNow();
if (currentTimeout == null) {
long spentTime = System.currentTimeMillis() - startTime;
long remainTime = unit.toMillis(timeout) - spentTime;
if (remainTime > 0) {
final RFuture<V> pollFuture = RedissonBlockingFairQueue.super.pollLastAndOfferFirstToAsync(queueName, remainTime, TimeUnit.MILLISECONDS);
pollFuture.addListener(new FutureListener<V>() {
@Override
public void operationComplete(Future<V> future) throws Exception {
unsubscribe(subscribeFuture);
if (!future.isSuccess()) {
promise.tryFailure(future.cause());
return;
}
promise.trySuccess(future.getNow());
}
});
} else {
unsubscribe(subscribeFuture);
promise.trySuccess(null);
}
} else {
final RedissonLockEntry entry = getEntry();
synchronized (entry) {
if (entry.getLatch().tryAcquire()) {
tryPollAsync(startTime, timeout, unit, subscribeFuture, promise);
} else {
final AtomicBoolean executed = new AtomicBoolean();
final AtomicReference<Timeout> futureRef = new AtomicReference<Timeout>();
final Runnable listener = new Runnable() {
@Override
public void run() {
executed.set(true);
if (futureRef.get() != null) {
futureRef.get().cancel();
}
tryPollLastAndOfferFirstToAsync(startTime, timeout, unit, subscribeFuture, promise, queueName);
}
};
entry.addListener(listener);
if (!executed.get()) {
long spentTime = System.currentTimeMillis() - startTime;
long remainTime = unit.toMillis(timeout) - spentTime;
Timeout scheduledFuture = commandExecutor.getConnectionManager().newTimeout(new TimerTask() {
@Override
public void run(Timeout t) throws Exception {
synchronized (entry) {
if (entry.removeListener(listener)) {
tryPollLastAndOfferFirstToAsync(startTime, timeout, unit, subscribeFuture, promise, queueName);
}
}
}
}, remainTime, TimeUnit.MILLISECONDS);
futureRef.set(scheduledFuture);
}
}
}
}
}
;
});
}
use of org.redisson.api.RFuture in project redisson by redisson.
the class RedissonBlockingFairQueue method tryTakeAsync.
private void tryTakeAsync(final RFuture<RedissonLockEntry> subscribeFuture, final RPromise<V> promise) {
if (promise.isDone()) {
unsubscribe(subscribeFuture);
return;
}
RFuture<Long> tryAcquireFuture = tryAcquireAsync();
tryAcquireFuture.addListener(new FutureListener<Long>() {
@Override
public void operationComplete(Future<Long> future) throws Exception {
if (!future.isSuccess()) {
unsubscribe(subscribeFuture);
promise.tryFailure(future.cause());
return;
}
Long currentTimeout = future.getNow();
if (currentTimeout == null) {
final RFuture<V> pollFuture = RedissonBlockingFairQueue.super.takeAsync();
pollFuture.addListener(new FutureListener<V>() {
@Override
public void operationComplete(Future<V> future) throws Exception {
unsubscribe(subscribeFuture);
if (!future.isSuccess()) {
promise.tryFailure(future.cause());
return;
}
promise.trySuccess(future.getNow());
}
});
} else {
final RedissonLockEntry entry = getEntry();
synchronized (entry) {
if (entry.getLatch().tryAcquire()) {
tryTakeAsync(subscribeFuture, promise);
} else {
final AtomicBoolean executed = new AtomicBoolean();
final AtomicReference<Timeout> futureRef = new AtomicReference<Timeout>();
final Runnable listener = new Runnable() {
@Override
public void run() {
executed.set(true);
if (futureRef.get() != null) {
futureRef.get().cancel();
}
tryTakeAsync(subscribeFuture, promise);
}
};
entry.addListener(listener);
if (!executed.get()) {
Timeout scheduledFuture = commandExecutor.getConnectionManager().newTimeout(new TimerTask() {
@Override
public void run(Timeout t) throws Exception {
synchronized (entry) {
if (entry.removeListener(listener)) {
tryTakeAsync(subscribeFuture, promise);
}
}
}
}, currentTimeout, TimeUnit.MILLISECONDS);
futureRef.set(scheduledFuture);
}
}
}
}
}
;
});
}
use of org.redisson.api.RFuture in project redisson by redisson.
the class RedissonRemoteService method subscribe.
private <T> void subscribe(final Class<T> remoteInterface, final RBlockingQueue<RemoteServiceRequest> requestQueue, final ExecutorService executor) {
RFuture<RemoteServiceRequest> take = requestQueue.takeAsync();
take.addListener(new FutureListener<RemoteServiceRequest>() {
@Override
public void operationComplete(Future<RemoteServiceRequest> future) throws Exception {
if (!future.isSuccess()) {
if (future.cause() instanceof RedissonShutdownException) {
return;
}
log.error("Can't process the remote service request.", future.cause());
// re-subscribe after a failed takeAsync
subscribe(remoteInterface, requestQueue, executor);
return;
}
// do not subscribe now, see
// https://github.com/mrniko/redisson/issues/493
// subscribe(remoteInterface, requestQueue);
final RemoteServiceRequest request = future.getNow();
// check the ack only if expected
if (request.getOptions().isAckExpected() && System.currentTimeMillis() - request.getDate() > request.getOptions().getAckTimeoutInMillis()) {
log.debug("request: {} has been skipped due to ackTimeout");
// re-subscribe after a skipped ackTimeout
subscribe(remoteInterface, requestQueue, executor);
return;
}
final String responseName = getResponseQueueName(remoteInterface, request.getRequestId());
// send the ack only if expected
if (request.getOptions().isAckExpected()) {
String ackName = getAckName(remoteInterface, request.getRequestId());
RFuture<Boolean> ackClientsFuture = commandExecutor.evalWriteAsync(responseName, LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN, "if redis.call('setnx', KEYS[1], 1) == 1 then " + "redis.call('pexpire', KEYS[1], ARGV[2]);" + "redis.call('rpush', KEYS[2], ARGV[1]);" + "redis.call('pexpire', KEYS[2], ARGV[2]);" + "return 1;" + "end;" + "return 0;", Arrays.<Object>asList(ackName, responseName), encode(new RemoteServiceAck()), request.getOptions().getAckTimeoutInMillis());
ackClientsFuture.addListener(new FutureListener<Boolean>() {
@Override
public void operationComplete(Future<Boolean> future) throws Exception {
if (!future.isSuccess()) {
log.error("Can't send ack for request: " + request, future.cause());
if (future.cause() instanceof RedissonShutdownException) {
return;
}
// re-subscribe after a failed send (ack)
subscribe(remoteInterface, requestQueue, executor);
return;
}
if (!future.getNow()) {
subscribe(remoteInterface, requestQueue, executor);
return;
}
executeMethod(remoteInterface, requestQueue, executor, request);
}
});
} else {
executeMethod(remoteInterface, requestQueue, executor, request);
}
}
});
}
use of org.redisson.api.RFuture in project redisson by redisson.
the class RedissonKeys method deleteByPatternAsync.
@Override
public RFuture<Long> deleteByPatternAsync(String pattern) {
if (!commandExecutor.getConnectionManager().isClusterMode()) {
return commandExecutor.evalWriteAsync((String) null, null, RedisCommands.EVAL_LONG, "local keys = redis.call('keys', ARGV[1]) " + "local n = 0 " + "for i=1, #keys,5000 do " + "n = n + redis.call('del', unpack(keys, i, math.min(i+4999, table.getn(keys)))) " + "end " + "return n;", Collections.emptyList(), pattern);
}
final RPromise<Long> result = commandExecutor.getConnectionManager().newPromise();
final AtomicReference<Throwable> failed = new AtomicReference<Throwable>();
final AtomicLong count = new AtomicLong();
Set<MasterSlaveEntry> entries = commandExecutor.getConnectionManager().getEntrySet();
final AtomicLong executed = new AtomicLong(entries.size());
final FutureListener<Long> listener = new FutureListener<Long>() {
@Override
public void operationComplete(Future<Long> future) throws Exception {
if (future.isSuccess()) {
count.addAndGet(future.getNow());
} else {
failed.set(future.cause());
}
checkExecution(result, failed, count, executed);
}
};
for (MasterSlaveEntry entry : entries) {
RFuture<Collection<String>> findFuture = commandExecutor.readAsync(entry, null, RedisCommands.KEYS, pattern);
findFuture.addListener(new FutureListener<Collection<String>>() {
@Override
public void operationComplete(Future<Collection<String>> future) throws Exception {
if (!future.isSuccess()) {
failed.set(future.cause());
checkExecution(result, failed, count, executed);
return;
}
Collection<String> keys = future.getNow();
if (keys.isEmpty()) {
checkExecution(result, failed, count, executed);
return;
}
RFuture<Long> deleteFuture = deleteAsync(keys.toArray(new String[keys.size()]));
deleteFuture.addListener(listener);
}
});
}
return result;
}
use of org.redisson.api.RFuture in project redisson by redisson.
the class RedissonExecutorService method poll.
private <T> Future<T> poll(List<Future<T>> futures, long timeout, TimeUnit timeUnit) throws InterruptedException {
final CountDownLatch latch = new CountDownLatch(1);
final AtomicReference<Future<T>> result = new AtomicReference<Future<T>>();
FutureListener<T> listener = new FutureListener<T>() {
@Override
public void operationComplete(io.netty.util.concurrent.Future<T> future) throws Exception {
latch.countDown();
result.compareAndSet(null, future);
}
};
for (Future<T> future : futures) {
RFuture<T> f = (RFuture<T>) future;
f.addListener(listener);
}
if (timeout == -1) {
latch.await();
} else {
latch.await(timeout, timeUnit);
}
for (Future<T> future : futures) {
RFuture<T> f = (RFuture<T>) future;
f.removeListener(listener);
}
return result.get();
}
Aggregations