Search in sources :

Example 6 with RFuture

use of org.redisson.api.RFuture in project redisson by redisson.

the class ClusterConnectionManager method addMasterEntry.

private RFuture<Collection<RFuture<Void>>> addMasterEntry(final ClusterPartition partition, final ClusterServersConfig cfg) {
    if (partition.isMasterFail()) {
        RedisException e = new RedisException("Failed to add master: " + partition.getMasterAddress() + " for slot ranges: " + partition.getSlotRanges() + ". Reason - server has FAIL flag");
        if (partition.getSlotRanges().isEmpty()) {
            e = new RedisException("Failed to add master: " + partition.getMasterAddress() + ". Reason - server has FAIL flag");
        }
        return newFailedFuture(e);
    }
    final RPromise<Collection<RFuture<Void>>> result = newPromise();
    RFuture<RedisConnection> connectionFuture = connect(cfg, partition.getMasterAddress());
    connectionFuture.addListener(new FutureListener<RedisConnection>() {

        @Override
        public void operationComplete(Future<RedisConnection> future) throws Exception {
            if (!future.isSuccess()) {
                log.error("Can't connect to master: {} with slot ranges: {}", partition.getMasterAddress(), partition.getSlotRanges());
                result.tryFailure(future.cause());
                return;
            }
            final RedisConnection connection = future.getNow();
            RFuture<Map<String, String>> clusterFuture = connection.async(RedisCommands.CLUSTER_INFO);
            clusterFuture.addListener(new FutureListener<Map<String, String>>() {

                @Override
                public void operationComplete(Future<Map<String, String>> future) throws Exception {
                    if (!future.isSuccess()) {
                        log.error("Can't execute CLUSTER_INFO for " + connection.getRedisClient().getAddr(), future.cause());
                        result.tryFailure(future.cause());
                        return;
                    }
                    Map<String, String> params = future.getNow();
                    if ("fail".equals(params.get("cluster_state"))) {
                        RedisException e = new RedisException("Failed to add master: " + partition.getMasterAddress() + " for slot ranges: " + partition.getSlotRanges() + ". Reason - cluster_state:fail");
                        log.error("cluster_state:fail for " + connection.getRedisClient().getAddr());
                        result.tryFailure(e);
                        return;
                    }
                    MasterSlaveServersConfig config = create(cfg);
                    config.setMasterAddress(partition.getMasterAddress());
                    final MasterSlaveEntry e;
                    List<RFuture<Void>> futures = new ArrayList<RFuture<Void>>();
                    if (config.getReadMode() == ReadMode.MASTER) {
                        e = new SingleEntry(partition.getSlotRanges(), ClusterConnectionManager.this, config);
                    } else {
                        config.setSlaveAddresses(partition.getSlaveAddresses());
                        e = new MasterSlaveEntry(partition.getSlotRanges(), ClusterConnectionManager.this, config);
                        List<RFuture<Void>> fs = e.initSlaveBalancer(partition.getFailedSlaveAddresses());
                        futures.addAll(fs);
                        if (!partition.getSlaveAddresses().isEmpty()) {
                            log.info("slaves: {} added for slot ranges: {}", partition.getSlaveAddresses(), partition.getSlotRanges());
                            if (!partition.getFailedSlaveAddresses().isEmpty()) {
                                log.warn("slaves: {} is down for slot ranges: {}", partition.getFailedSlaveAddresses(), partition.getSlotRanges());
                            }
                        }
                    }
                    RFuture<Void> f = e.setupMasterEntry(config.getMasterAddress().getHost(), config.getMasterAddress().getPort());
                    final RPromise<Void> initFuture = newPromise();
                    futures.add(initFuture);
                    f.addListener(new FutureListener<Void>() {

                        @Override
                        public void operationComplete(Future<Void> future) throws Exception {
                            if (!future.isSuccess()) {
                                log.error("Can't add master: {} for slot ranges: {}", partition.getMasterAddress(), partition.getSlotRanges());
                                initFuture.tryFailure(future.cause());
                                return;
                            }
                            for (Integer slot : partition.getSlots()) {
                                addEntry(slot, e);
                                lastPartitions.put(slot, partition);
                            }
                            log.info("master: {} added for slot ranges: {}", partition.getMasterAddress(), partition.getSlotRanges());
                            if (!initFuture.trySuccess(null)) {
                                throw new IllegalStateException();
                            }
                        }
                    });
                    if (!result.trySuccess(futures)) {
                        throw new IllegalStateException();
                    }
                }
            });
        }
    });
    return result;
}
Also used : ArrayList(java.util.ArrayList) MasterSlaveEntry(org.redisson.connection.MasterSlaveEntry) RedisException(org.redisson.client.RedisException) FutureListener(io.netty.util.concurrent.FutureListener) SingleEntry(org.redisson.connection.SingleEntry) MasterSlaveServersConfig(org.redisson.config.MasterSlaveServersConfig) RFuture(org.redisson.api.RFuture) RedisException(org.redisson.client.RedisException) RedisConnectionException(org.redisson.client.RedisConnectionException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Collection(java.util.Collection) ScheduledFuture(io.netty.util.concurrent.ScheduledFuture) RFuture(org.redisson.api.RFuture) Future(io.netty.util.concurrent.Future) RedisConnection(org.redisson.client.RedisConnection)

Example 7 with RFuture

use of org.redisson.api.RFuture in project redisson by redisson.

the class RedisClientTest method testConnectAsync.

@Test
public void testConnectAsync() throws InterruptedException {
    RedisClient c = new RedisClient(RedisRunner.getDefaultRedisServerBindAddressAndPort());
    RFuture<RedisConnection> f = c.connectAsync();
    final CountDownLatch l = new CountDownLatch(1);
    f.addListener((FutureListener<RedisConnection>) future -> {
        RedisConnection conn = future.get();
        assertThat(conn.sync(RedisCommands.PING)).isEqualTo("PONG");
        l.countDown();
    });
    assertThat(l.await(10, TimeUnit.SECONDS)).isTrue();
}
Also used : RedisClient(org.redisson.client.RedisClient) PubSubType(org.redisson.client.protocol.pubsub.PubSubType) RPromise(org.redisson.misc.RPromise) Arrays(java.util.Arrays) RedisConnection(org.redisson.client.RedisConnection) BeforeClass(org.junit.BeforeClass) StringCodec(org.redisson.client.codec.StringCodec) Assertions.assertThat(org.assertj.core.api.Assertions.assertThat) RedisClient(org.redisson.client.RedisClient) ArrayList(java.util.ArrayList) RFuture(org.redisson.api.RFuture) RedisPubSubListener(org.redisson.client.RedisPubSubListener) Map(java.util.Map) After(org.junit.After) ExecutorService(java.util.concurrent.ExecutorService) Before(org.junit.Before) RedisPubSubConnection(org.redisson.client.RedisPubSubConnection) AfterClass(org.junit.AfterClass) LongCodec(org.redisson.client.codec.LongCodec) FutureListener(io.netty.util.concurrent.FutureListener) RedissonPromise(org.redisson.misc.RedissonPromise) IOException(java.io.IOException) Test(org.junit.Test) CommandData(org.redisson.client.protocol.CommandData) Executors(java.util.concurrent.Executors) RedisCommands(org.redisson.client.protocol.RedisCommands) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) CountDownLatch(java.util.concurrent.CountDownLatch) List(java.util.List) CommandsData(org.redisson.client.protocol.CommandsData) CountDownLatch(java.util.concurrent.CountDownLatch) RedisConnection(org.redisson.client.RedisConnection) Test(org.junit.Test)

Example 8 with RFuture

use of org.redisson.api.RFuture in project redisson by redisson.

the class RedissonMapCache method scanIteratorAsync.

public RFuture<MapScanResult<ScanObjectEntry, ScanObjectEntry>> scanIteratorAsync(final String name, InetSocketAddress client, long startPos) {
    RedisCommand<MapCacheScanResult<Object, Object>> EVAL_HSCAN = new RedisCommand<MapCacheScanResult<Object, Object>>("EVAL", new ListMultiDecoder(new LongMultiDecoder(), new ObjectMapDecoder(new MapScanCodec(codec)), new ObjectListDecoder(codec), new MapCacheScanResultReplayDecoder()), ValueType.MAP);
    RFuture<MapCacheScanResult<ScanObjectEntry, ScanObjectEntry>> f = commandExecutor.evalReadAsync(client, name, codec, EVAL_HSCAN, "local result = {}; " + "local idleKeys = {}; " + "local res = redis.call('hscan', KEYS[1], ARGV[2]); " + "local currentTime = tonumber(ARGV[1]); " + "for i, value in ipairs(res[2]) do " + "if i % 2 == 0 then " + "local key = res[2][i-1]; " + "local expireDate = 92233720368547758; " + "local expireDateScore = redis.call('zscore', KEYS[2], key); " + "if expireDateScore ~= false then " + "expireDate = tonumber(expireDateScore) " + "end; " + "local t, val = struct.unpack('dLc0', value); " + "if t ~= 0 then " + "local expireIdle = redis.call('zscore', KEYS[3], key); " + "if expireIdle ~= false then " + "if tonumber(expireIdle) > currentTime and expireDate > currentTime then " + "table.insert(idleKeys, key); " + "end; " + "expireDate = math.min(expireDate, tonumber(expireIdle)) " + "end; " + "end; " + "if expireDate > currentTime then " + "table.insert(result, key); " + "table.insert(result, val); " + "end; " + "end; " + "end;" + "return {res[1], result, idleKeys};", Arrays.<Object>asList(name, getTimeoutSetName(name), getIdleSetName(name)), System.currentTimeMillis(), startPos);
    f.addListener(new FutureListener<MapCacheScanResult<ScanObjectEntry, ScanObjectEntry>>() {

        @Override
        public void operationComplete(Future<MapCacheScanResult<ScanObjectEntry, ScanObjectEntry>> future) throws Exception {
            if (future.isSuccess()) {
                MapCacheScanResult<ScanObjectEntry, ScanObjectEntry> res = future.getNow();
                if (res.getIdleKeys().isEmpty()) {
                    return;
                }
                List<Object> args = new ArrayList<Object>(res.getIdleKeys().size() + 1);
                args.add(System.currentTimeMillis());
                args.addAll(res.getIdleKeys());
                commandExecutor.evalWriteAsync(name, codec, new RedisCommand<Map<Object, Object>>("EVAL", new MapGetAllDecoder(args, 1), 7, ValueType.MAP_KEY, ValueType.MAP_VALUE), // index is the first parameter
                "local currentTime = tonumber(table.remove(ARGV, 1)); " + "local map = redis.call('hmget', KEYS[1], unpack(ARGV)); " + "for i = #map, 1, -1 do " + "local value = map[i]; " + "if value ~= false then " + "local key = ARGV[i]; " + "local t, val = struct.unpack('dLc0', value); " + "if t ~= 0 then " + "local expireIdle = redis.call('zscore', KEYS[2], key); " + "if expireIdle ~= false then " + "if tonumber(expireIdle) > currentTime then " + "local value = struct.pack('dLc0', t, string.len(val), val); " + "redis.call('hset', KEYS[1], key, value); " + "redis.call('zadd', KEYS[2], t + currentTime, key); " + "end; " + "end; " + "end; " + "end; " + "end; ", Arrays.<Object>asList(name, getIdleSetName(name)), args.toArray());
            }
        }
    });
    return (RFuture<MapScanResult<ScanObjectEntry, ScanObjectEntry>>) (Object) f;
}
Also used : ObjectMapDecoder(org.redisson.client.protocol.decoder.ObjectMapDecoder) ListMultiDecoder(org.redisson.client.protocol.decoder.ListMultiDecoder) LongMultiDecoder(org.redisson.client.protocol.decoder.LongMultiDecoder) MapScanCodec(org.redisson.client.codec.MapScanCodec) RFuture(org.redisson.api.RFuture) ScanObjectEntry(org.redisson.client.protocol.decoder.ScanObjectEntry) MapCacheScanResult(org.redisson.client.protocol.decoder.MapCacheScanResult) MapCacheScanResultReplayDecoder(org.redisson.client.protocol.decoder.MapCacheScanResultReplayDecoder) RedisCommand(org.redisson.client.protocol.RedisCommand) MapGetAllDecoder(org.redisson.connection.decoder.MapGetAllDecoder) ArrayList(java.util.ArrayList) List(java.util.List) ObjectListDecoder(org.redisson.client.protocol.decoder.ObjectListDecoder)

Example 9 with RFuture

use of org.redisson.api.RFuture in project redisson by redisson.

the class BaseRemoteService method async.

private <T> T async(final Class<T> remoteInterface, final RemoteInvocationOptions options, final Class<?> syncInterface) {
    // local copy of the options, to prevent mutation
    final RemoteInvocationOptions optionsCopy = new RemoteInvocationOptions(options);
    final String toString = getClass().getSimpleName() + "-" + remoteInterface.getSimpleName() + "-proxy-" + generateRequestId();
    InvocationHandler handler = new InvocationHandler() {

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (method.getName().equals("toString")) {
                return toString;
            } else if (method.getName().equals("equals")) {
                return proxy == args[0];
            } else if (method.getName().equals("hashCode")) {
                return toString.hashCode();
            }
            if (!optionsCopy.isResultExpected() && !(method.getReturnType().equals(Void.class) || method.getReturnType().equals(Void.TYPE) || method.getReturnType().equals(RFuture.class))) {
                throw new IllegalArgumentException("The noResult option only supports void return value");
            }
            final String requestId = generateRequestId();
            final String requestQueueName = getRequestQueueName(syncInterface);
            final String responseName = getResponseQueueName(syncInterface, requestId);
            final String ackName = getAckName(syncInterface, requestId);
            final RBlockingQueue<RemoteServiceRequest> requestQueue = redisson.getBlockingQueue(requestQueueName, getCodec());
            final RemoteServiceRequest request = new RemoteServiceRequest(requestId, method.getName(), getMethodSignatures(method), args, optionsCopy, System.currentTimeMillis());
            final RemotePromise<Object> result = new RemotePromise<Object>(commandExecutor.getConnectionManager().newPromise()) {

                @Override
                public boolean cancel(boolean mayInterruptIfRunning) {
                    if (isCancelled()) {
                        return true;
                    }
                    if (isDone()) {
                        return false;
                    }
                    if (optionsCopy.isAckExpected()) {
                        RFuture<Boolean> future = 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('lrem', KEYS[3], 1, ARGV[1]);" + "redis.call('pexpire', KEYS[2], ARGV[2]);" + "return 1;" + "end;" + "return 0;", Arrays.<Object>asList(ackName, responseName, requestQueueName), encode(request), request.getOptions().getAckTimeoutInMillis());
                        boolean ackNotSent = commandExecutor.get(future);
                        if (ackNotSent) {
                            super.cancel(mayInterruptIfRunning);
                            return true;
                        }
                        return cancel(syncInterface, requestId, request, mayInterruptIfRunning);
                    }
                    boolean removed = remove(requestQueue, request);
                    if (removed) {
                        super.cancel(mayInterruptIfRunning);
                        return true;
                    }
                    return cancel(syncInterface, requestId, request, mayInterruptIfRunning);
                }

                private boolean cancel(Class<?> remoteInterface, String requestId, RemoteServiceRequest request, boolean mayInterruptIfRunning) {
                    if (isCancelled()) {
                        return true;
                    }
                    if (isDone()) {
                        return false;
                    }
                    String canceRequestName = getCancelRequestQueueName(remoteInterface, requestId);
                    cancelExecution(optionsCopy, responseName, request, mayInterruptIfRunning, canceRequestName, this);
                    awaitUninterruptibly(60, TimeUnit.SECONDS);
                    return isCancelled();
                }
            };
            result.setRequestId(requestId);
            RFuture<Boolean> addFuture = addAsync(requestQueue, request, result);
            addFuture.addListener(new FutureListener<Boolean>() {

                @Override
                public void operationComplete(Future<Boolean> future) throws Exception {
                    if (!future.isSuccess()) {
                        result.tryFailure(future.cause());
                        return;
                    }
                    if (optionsCopy.isAckExpected()) {
                        final RBlockingQueue<RemoteServiceAck> responseQueue = redisson.getBlockingQueue(responseName, getCodec());
                        RFuture<RemoteServiceAck> ackFuture = responseQueue.pollAsync(optionsCopy.getAckTimeoutInMillis(), TimeUnit.MILLISECONDS);
                        ackFuture.addListener(new FutureListener<RemoteServiceAck>() {

                            @Override
                            public void operationComplete(Future<RemoteServiceAck> future) throws Exception {
                                if (!future.isSuccess()) {
                                    result.tryFailure(future.cause());
                                    return;
                                }
                                RemoteServiceAck ack = future.getNow();
                                if (ack == null) {
                                    RFuture<RemoteServiceAck> ackFutureAttempt = tryPollAckAgainAsync(optionsCopy, responseQueue, ackName);
                                    ackFutureAttempt.addListener(new FutureListener<RemoteServiceAck>() {

                                        @Override
                                        public void operationComplete(Future<RemoteServiceAck> future) throws Exception {
                                            if (!future.isSuccess()) {
                                                result.tryFailure(future.cause());
                                                return;
                                            }
                                            if (future.getNow() == null) {
                                                Exception ex = new RemoteServiceAckTimeoutException("No ACK response after " + optionsCopy.getAckTimeoutInMillis() + "ms for request: " + request);
                                                result.tryFailure(ex);
                                                return;
                                            }
                                            awaitResultAsync(optionsCopy, result, request, responseName, ackName);
                                        }
                                    });
                                } else {
                                    awaitResultAsync(optionsCopy, result, request, responseName);
                                }
                            }
                        });
                    } else {
                        awaitResultAsync(optionsCopy, result, request, responseName);
                    }
                }
            });
            return result;
        }
    };
    return (T) Proxy.newProxyInstance(remoteInterface.getClassLoader(), new Class[] { remoteInterface }, handler);
}
Also used : RBlockingQueue(org.redisson.api.RBlockingQueue) RemoteServiceAck(org.redisson.remote.RemoteServiceAck) FutureListener(io.netty.util.concurrent.FutureListener) Method(java.lang.reflect.Method) RFuture(org.redisson.api.RFuture) InvocationHandler(java.lang.reflect.InvocationHandler) RemoteServiceTimeoutException(org.redisson.remote.RemoteServiceTimeoutException) IOException(java.io.IOException) RemoteServiceAckTimeoutException(org.redisson.remote.RemoteServiceAckTimeoutException) RemoteInvocationOptions(org.redisson.api.RemoteInvocationOptions) RemoteServiceRequest(org.redisson.remote.RemoteServiceRequest) RFuture(org.redisson.api.RFuture) Future(io.netty.util.concurrent.Future) RemoteServiceAckTimeoutException(org.redisson.remote.RemoteServiceAckTimeoutException) RemotePromise(org.redisson.executor.RemotePromise)

Example 10 with RFuture

use of org.redisson.api.RFuture in project redisson by redisson.

the class RedisNodes method pingAll.

@Override
public boolean pingAll() {
    List<RedisClientEntry> clients = new ArrayList<RedisClientEntry>(connectionManager.getClients());
    final Map<RedisConnection, RFuture<String>> result = new ConcurrentHashMap<RedisConnection, RFuture<String>>(clients.size());
    final CountDownLatch latch = new CountDownLatch(clients.size());
    for (RedisClientEntry entry : clients) {
        RFuture<RedisConnection> f = entry.getClient().connectAsync();
        f.addListener(new FutureListener<RedisConnection>() {

            @Override
            public void operationComplete(Future<RedisConnection> future) throws Exception {
                if (future.isSuccess()) {
                    final RedisConnection c = future.getNow();
                    RPromise<RedisConnection> connectionFuture = connectionManager.newPromise();
                    connectionManager.getConnectListener().onConnect(connectionFuture, c, null, connectionManager.getConfig());
                    connectionFuture.addListener(new FutureListener<RedisConnection>() {

                        @Override
                        public void operationComplete(Future<RedisConnection> future) throws Exception {
                            RFuture<String> r = c.async(connectionManager.getConfig().getPingTimeout(), RedisCommands.PING);
                            result.put(c, r);
                            latch.countDown();
                        }
                    });
                } else {
                    latch.countDown();
                }
            }
        });
    }
    long time = System.currentTimeMillis();
    try {
        latch.await();
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
    if (System.currentTimeMillis() - time >= connectionManager.getConfig().getConnectTimeout()) {
        for (Entry<RedisConnection, RFuture<String>> entry : result.entrySet()) {
            entry.getKey().closeAsync();
        }
        return false;
    }
    time = System.currentTimeMillis();
    boolean res = true;
    for (Entry<RedisConnection, RFuture<String>> entry : result.entrySet()) {
        RFuture<String> f = entry.getValue();
        f.awaitUninterruptibly();
        if (!"PONG".equals(f.getNow())) {
            res = false;
        }
        entry.getKey().closeAsync();
    }
    // true and no futures missed during client connection
    return res && result.size() == clients.size();
}
Also used : FutureListener(io.netty.util.concurrent.FutureListener) RPromise(org.redisson.misc.RPromise) ArrayList(java.util.ArrayList) RFuture(org.redisson.api.RFuture) CountDownLatch(java.util.concurrent.CountDownLatch) RFuture(org.redisson.api.RFuture) Future(io.netty.util.concurrent.Future) RedisClientEntry(org.redisson.connection.RedisClientEntry) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) RedisConnection(org.redisson.client.RedisConnection)

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