Search in sources :

Example 11 with RFuture

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);
                        }
                    }
                }
            }
        }

        ;
    });
}
Also used : FutureListener(io.netty.util.concurrent.FutureListener) Timeout(io.netty.util.Timeout) AtomicReference(java.util.concurrent.atomic.AtomicReference) RFuture(org.redisson.api.RFuture) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) TimerTask(io.netty.util.TimerTask) RFuture(org.redisson.api.RFuture) Future(io.netty.util.concurrent.Future)

Example 12 with RFuture

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);
                        }
                    }
                }
            }
        }

        ;
    });
}
Also used : FutureListener(io.netty.util.concurrent.FutureListener) Timeout(io.netty.util.Timeout) AtomicReference(java.util.concurrent.atomic.AtomicReference) RFuture(org.redisson.api.RFuture) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) TimerTask(io.netty.util.TimerTask) RFuture(org.redisson.api.RFuture) Future(io.netty.util.concurrent.Future)

Example 13 with RFuture

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);
            }
        }
    });
}
Also used : FutureListener(io.netty.util.concurrent.FutureListener) RFuture(org.redisson.api.RFuture) RemoteServiceRequest(org.redisson.remote.RemoteServiceRequest) RFuture(org.redisson.api.RFuture) Future(io.netty.util.concurrent.Future) RemoteServiceAck(org.redisson.remote.RemoteServiceAck)

Example 14 with RFuture

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;
}
Also used : FutureListener(io.netty.util.concurrent.FutureListener) AtomicReference(java.util.concurrent.atomic.AtomicReference) RFuture(org.redisson.api.RFuture) RedisException(org.redisson.client.RedisException) AtomicLong(java.util.concurrent.atomic.AtomicLong) MasterSlaveEntry(org.redisson.connection.MasterSlaveEntry) AtomicLong(java.util.concurrent.atomic.AtomicLong) RFuture(org.redisson.api.RFuture) Future(io.netty.util.concurrent.Future) Collection(java.util.Collection)

Example 15 with RFuture

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();
}
Also used : FutureListener(io.netty.util.concurrent.FutureListener) ScheduledFuture(java.util.concurrent.ScheduledFuture) RScheduledFuture(org.redisson.api.RScheduledFuture) Future(java.util.concurrent.Future) RedissonScheduledFuture(org.redisson.executor.RedissonScheduledFuture) RFuture(org.redisson.api.RFuture) AtomicReference(java.util.concurrent.atomic.AtomicReference) CountDownLatch(java.util.concurrent.CountDownLatch) RFuture(org.redisson.api.RFuture)

Aggregations

RFuture (org.redisson.api.RFuture)29 FutureListener (io.netty.util.concurrent.FutureListener)23 Future (io.netty.util.concurrent.Future)21 ArrayList (java.util.ArrayList)9 AtomicReference (java.util.concurrent.atomic.AtomicReference)9 Timeout (io.netty.util.Timeout)7 TimerTask (io.netty.util.TimerTask)7 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)7 RedisConnection (org.redisson.client.RedisConnection)7 AtomicLong (java.util.concurrent.atomic.AtomicLong)6 RedisConnectionException (org.redisson.client.RedisConnectionException)6 RedisException (org.redisson.client.RedisException)6 MasterSlaveEntry (org.redisson.connection.MasterSlaveEntry)6 ScheduledFuture (io.netty.util.concurrent.ScheduledFuture)5 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)5 Collection (java.util.Collection)4 RPromise (org.redisson.misc.RPromise)4 ChannelFuture (io.netty.channel.ChannelFuture)3 ChannelFutureListener (io.netty.channel.ChannelFutureListener)3 URL (java.net.URL)3