Search in sources :

Example 1 with BatchCommandData

use of org.redisson.client.protocol.BatchCommandData in project redisson by redisson.

the class BaseRedisBatchExecutor method addBatchCommandData.

protected final void addBatchCommandData(Object[] batchParams) {
    MasterSlaveEntry msEntry = getEntry(source);
    Entry entry = commands.get(msEntry);
    if (entry == null) {
        entry = new Entry();
        Entry oldEntry = commands.putIfAbsent(msEntry, entry);
        if (oldEntry != null) {
            entry = oldEntry;
        }
    }
    if (!readOnlyMode) {
        entry.setReadOnlyMode(false);
    }
    Codec codecToUse = getCodec(codec);
    BatchCommandData<V, R> commandData = new BatchCommandData<V, R>(mainPromise, codecToUse, command, batchParams, index.incrementAndGet());
    entry.getCommands().add(commandData);
}
Also used : MasterSlaveEntry(org.redisson.connection.MasterSlaveEntry) Entry(org.redisson.command.CommandBatchService.Entry) Codec(org.redisson.client.codec.Codec) BatchCommandData(org.redisson.client.protocol.BatchCommandData) MasterSlaveEntry(org.redisson.connection.MasterSlaveEntry)

Example 2 with BatchCommandData

use of org.redisson.client.protocol.BatchCommandData in project redisson by redisson.

the class CommandBatchService method executeAsyncVoid.

private RFuture<Void> executeAsyncVoid(boolean noResult) {
    if (executed) {
        throw new IllegalStateException("Batch already executed!");
    }
    if (commands.isEmpty()) {
        return connectionManager.newSucceededFuture(null);
    }
    if (noResult) {
        for (Entry entry : commands.values()) {
            RPromise<Object> s = connectionManager.newPromise();
            BatchCommandData commandData = new BatchCommandData(s, null, RedisCommands.CLIENT_REPLY, new Object[] { "OFF" }, index.incrementAndGet());
            entry.getCommands().addFirst(commandData);
            RPromise<Object> s1 = connectionManager.newPromise();
            BatchCommandData commandData1 = new BatchCommandData(s1, null, RedisCommands.CLIENT_REPLY, new Object[] { "ON" }, index.incrementAndGet());
            entry.getCommands().add(commandData1);
        }
    }
    executed = true;
    RPromise<Void> voidPromise = connectionManager.newPromise();
    voidPromise.addListener(new FutureListener<Void>() {

        @Override
        public void operationComplete(Future<Void> future) throws Exception {
            commands = null;
        }
    });
    AtomicInteger slots = new AtomicInteger(commands.size());
    for (java.util.Map.Entry<MasterSlaveEntry, Entry> e : commands.entrySet()) {
        execute(e.getValue(), new NodeSource(e.getKey()), voidPromise, slots, 0, true);
    }
    return voidPromise;
}
Also used : BatchCommandData(org.redisson.client.protocol.BatchCommandData) RedisMovedException(org.redisson.client.RedisMovedException) RedisAskException(org.redisson.client.RedisAskException) WriteRedisConnectionException(org.redisson.client.WriteRedisConnectionException) RedisLoadingException(org.redisson.client.RedisLoadingException) RedisTryAgainException(org.redisson.client.RedisTryAgainException) RedisTimeoutException(org.redisson.client.RedisTimeoutException) NodeSource(org.redisson.connection.NodeSource) MasterSlaveEntry(org.redisson.connection.MasterSlaveEntry) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) MasterSlaveEntry(org.redisson.connection.MasterSlaveEntry) ConcurrentMap(java.util.concurrent.ConcurrentMap)

Example 3 with BatchCommandData

use of org.redisson.client.protocol.BatchCommandData in project redisson by redisson.

the class CommandBatchService method async.

@Override
protected <V, R> void async(boolean readOnlyMode, NodeSource nodeSource, Codec codec, RedisCommand<V> command, Object[] params, RPromise<R> mainPromise, int attempt) {
    if (executed) {
        throw new IllegalStateException("Batch already has been executed!");
    }
    Entry entry = commands.get(nodeSource.getEntry());
    if (entry == null) {
        entry = new Entry();
        Entry oldEntry = commands.putIfAbsent(nodeSource.getEntry(), entry);
        if (oldEntry != null) {
            entry = oldEntry;
        }
    }
    if (!readOnlyMode) {
        entry.setReadOnlyMode(false);
    }
    if (isRedissonReferenceSupportEnabled()) {
        for (int i = 0; i < params.length; i++) {
            RedissonReference reference = redisson != null ? RedissonObjectFactory.toReference(redisson, params[i]) : RedissonObjectFactory.toReference(redissonReactive, params[i]);
            if (reference != null) {
                params[i] = reference;
            }
        }
    }
    BatchCommandData<V, R> commandData = new BatchCommandData<V, R>(mainPromise, codec, command, params, index.incrementAndGet());
    entry.getCommands().add(commandData);
}
Also used : MasterSlaveEntry(org.redisson.connection.MasterSlaveEntry) RedissonReference(org.redisson.RedissonReference) BatchCommandData(org.redisson.client.protocol.BatchCommandData)

Example 4 with BatchCommandData

use of org.redisson.client.protocol.BatchCommandData in project redisson by redisson.

the class CommandBatchService method checkConnectionFuture.

private void checkConnectionFuture(final Entry entry, final NodeSource source, final RPromise<Void> mainPromise, final RPromise<Void> attemptPromise, final AsyncDetails details, RFuture<RedisConnection> connFuture, final boolean noResult) {
    if (attemptPromise.isDone() || mainPromise.isCancelled() || connFuture.isCancelled()) {
        return;
    }
    if (!connFuture.isSuccess()) {
        connectionManager.getShutdownLatch().release();
        details.setException(convertException(connFuture));
        return;
    }
    final RedisConnection connection = connFuture.getNow();
    List<CommandData<?, ?>> list = new ArrayList<CommandData<?, ?>>(entry.getCommands().size() + 1);
    if (source.getRedirect() == Redirect.ASK) {
        RPromise<Void> promise = connectionManager.newPromise();
        list.add(new CommandData<Void, Void>(promise, StringCodec.INSTANCE, RedisCommands.ASKING, new Object[] {}));
    }
    for (BatchCommandData<?, ?> c : entry.getCommands()) {
        if (c.getPromise().isSuccess()) {
            // skip successful commands
            continue;
        }
        list.add(c);
    }
    ChannelFuture future = connection.send(new CommandsData(attemptPromise, list, noResult));
    details.setWriteFuture(future);
    details.getWriteFuture().addListener(new ChannelFutureListener() {

        @Override
        public void operationComplete(ChannelFuture future) throws Exception {
            checkWriteFuture(attemptPromise, details, connection, future, noResult);
        }
    });
    releaseConnection(source, connFuture, entry.isReadOnlyMode(), attemptPromise, details);
}
Also used : ChannelFuture(io.netty.channel.ChannelFuture) ArrayList(java.util.ArrayList) ChannelFutureListener(io.netty.channel.ChannelFutureListener) RedisMovedException(org.redisson.client.RedisMovedException) RedisAskException(org.redisson.client.RedisAskException) WriteRedisConnectionException(org.redisson.client.WriteRedisConnectionException) RedisLoadingException(org.redisson.client.RedisLoadingException) RedisTryAgainException(org.redisson.client.RedisTryAgainException) RedisTimeoutException(org.redisson.client.RedisTimeoutException) CommandsData(org.redisson.client.protocol.CommandsData) BatchCommandData(org.redisson.client.protocol.BatchCommandData) CommandData(org.redisson.client.protocol.CommandData) RedisConnection(org.redisson.client.RedisConnection)

Example 5 with BatchCommandData

use of org.redisson.client.protocol.BatchCommandData 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;
}
Also used : RPromise(org.redisson.misc.RPromise) java.util(java.util) RedisConnection(org.redisson.client.RedisConnection) Codec(org.redisson.client.codec.Codec) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ExecutionMode(org.redisson.api.BatchOptions.ExecutionMode) RFuture(org.redisson.api.RFuture) NodeSource(org.redisson.connection.NodeSource) CompletableFutureWrapper(org.redisson.misc.CompletableFutureWrapper) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) TimerTask(io.netty.util.TimerTask) BatchCommandData(org.redisson.client.protocol.BatchCommandData) Timeout(io.netty.util.Timeout) ConnectionManager(org.redisson.connection.ConnectionManager) java.util.concurrent(java.util.concurrent) RedissonPromise(org.redisson.misc.RedissonPromise) CommandData(org.redisson.client.protocol.CommandData) BatchOptions(org.redisson.api.BatchOptions) RedisTimeoutException(org.redisson.client.RedisTimeoutException) Collectors(java.util.stream.Collectors) BatchResult(org.redisson.api.BatchResult) RedisCommands(org.redisson.client.protocol.RedisCommands) ReferenceCountUtil(io.netty.util.ReferenceCountUtil) MasterSlaveEntry(org.redisson.connection.MasterSlaveEntry) RedisCommand(org.redisson.client.protocol.RedisCommand) RedissonObjectBuilder(org.redisson.liveobject.core.RedissonObjectBuilder) RedissonPromise(org.redisson.misc.RedissonPromise) BatchCommandData(org.redisson.client.protocol.BatchCommandData) BatchResult(org.redisson.api.BatchResult) NodeSource(org.redisson.connection.NodeSource) MasterSlaveEntry(org.redisson.connection.MasterSlaveEntry) TimerTask(io.netty.util.TimerTask) MasterSlaveEntry(org.redisson.connection.MasterSlaveEntry) Timeout(io.netty.util.Timeout) RedisTimeoutException(org.redisson.client.RedisTimeoutException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) RedisTimeoutException(org.redisson.client.RedisTimeoutException)

Aggregations

BatchCommandData (org.redisson.client.protocol.BatchCommandData)6 MasterSlaveEntry (org.redisson.connection.MasterSlaveEntry)5 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)3 RedisTimeoutException (org.redisson.client.RedisTimeoutException)3 NodeSource (org.redisson.connection.NodeSource)3 BatchResult (org.redisson.api.BatchResult)2 RFuture (org.redisson.api.RFuture)2 RedisAskException (org.redisson.client.RedisAskException)2 RedisConnection (org.redisson.client.RedisConnection)2 RedisLoadingException (org.redisson.client.RedisLoadingException)2 RedisMovedException (org.redisson.client.RedisMovedException)2 RedisTryAgainException (org.redisson.client.RedisTryAgainException)2 WriteRedisConnectionException (org.redisson.client.WriteRedisConnectionException)2 Codec (org.redisson.client.codec.Codec)2 CommandData (org.redisson.client.protocol.CommandData)2 RedissonPromise (org.redisson.misc.RedissonPromise)2 ChannelFuture (io.netty.channel.ChannelFuture)1 ChannelFutureListener (io.netty.channel.ChannelFutureListener)1 ReferenceCountUtil (io.netty.util.ReferenceCountUtil)1 Timeout (io.netty.util.Timeout)1