Search in sources :

Example 6 with BatchCommandData

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

the class CommandBatchService method executeAsync.

public RFuture<BatchResult<?>> executeAsync() {
    if (executed.get()) {
        throw new IllegalStateException("Batch already executed!");
    }
    if (commands.isEmpty()) {
        executed.set(true);
        BatchResult<Object> result = new BatchResult<>(Collections.emptyList(), 0);
        return RedissonPromise.newSucceededFuture(result);
    }
    if (isRedisBasedQueue()) {
        return executeRedisBasedQueue();
    }
    if (this.options.getExecutionMode() != ExecutionMode.IN_MEMORY) {
        for (Entry entry : commands.values()) {
            BatchCommandData<?, ?> multiCommand = new BatchCommandData(RedisCommands.MULTI, new Object[] {}, index.incrementAndGet());
            entry.getCommands().addFirst(multiCommand);
            BatchCommandData<?, ?> execCommand = new BatchCommandData(RedisCommands.EXEC, new Object[] {}, index.incrementAndGet());
            entry.getCommands().add(execCommand);
        }
    }
    if (this.options.isSkipResult()) {
        for (Entry entry : commands.values()) {
            BatchCommandData<?, ?> offCommand = new BatchCommandData(RedisCommands.CLIENT_REPLY, new Object[] { "OFF" }, index.incrementAndGet());
            entry.getCommands().addFirst(offCommand);
            BatchCommandData<?, ?> onCommand = new BatchCommandData(RedisCommands.CLIENT_REPLY, new Object[] { "ON" }, index.incrementAndGet());
            entry.getCommands().add(onCommand);
        }
    }
    if (this.options.getSyncSlaves() > 0) {
        for (Entry entry : commands.values()) {
            BatchCommandData<?, ?> waitCommand = new BatchCommandData(RedisCommands.WAIT, new Object[] { this.options.getSyncSlaves(), this.options.getSyncTimeout() }, index.incrementAndGet());
            entry.getCommands().add(waitCommand);
        }
    }
    RPromise<BatchResult<?>> promise = new RedissonPromise<>();
    CompletableFuture<Void> voidPromise = new CompletableFuture<>();
    if (this.options.isSkipResult() && this.options.getSyncSlaves() == 0) {
        voidPromise.whenComplete((res, ex) -> {
            executed.set(true);
            if (ex != null) {
                for (Entry e : commands.values()) {
                    e.getCommands().forEach(t -> t.tryFailure(ex));
                }
                promise.tryFailure(ex);
                commands.clear();
                nestedServices.clear();
                return;
            }
            commands.clear();
            nestedServices.clear();
            promise.trySuccess(new BatchResult<>(Collections.emptyList(), 0));
        });
    } else {
        voidPromise.whenComplete((res, ex) -> {
            executed.set(true);
            if (ex != null) {
                for (Entry e : commands.values()) {
                    e.getCommands().forEach(t -> t.tryFailure(ex));
                }
                promise.tryFailure(ex);
                commands.clear();
                nestedServices.clear();
                return;
            }
            List<BatchCommandData> entries = new ArrayList<BatchCommandData>();
            for (Entry e : commands.values()) {
                entries.addAll(e.getCommands());
            }
            Collections.sort(entries);
            List<Object> responses = new ArrayList<Object>(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()) && !this.options.isSkipResult()) {
                    if (commandEntry.getPromise().isCancelled()) {
                        continue;
                    }
                    Object entryResult = commandEntry.getPromise().getNow(null);
                    try {
                        if (objectBuilder != null) {
                            entryResult = objectBuilder.tryHandleReference(entryResult, referenceType);
                        }
                    } catch (ReflectiveOperationException exc) {
                        log.error("Unable to handle reference from " + entryResult, exc);
                    }
                    responses.add(entryResult);
                }
            }
            BatchResult<Object> result = new BatchResult<Object>(responses, syncedSlaves);
            promise.trySuccess(result);
            commands.clear();
            nestedServices.clear();
        });
    }
    AtomicInteger slots = new AtomicInteger(commands.size());
    for (Map.Entry<RFuture<?>, List<CommandBatchService>> entry : nestedServices.entrySet()) {
        slots.incrementAndGet();
        for (CommandBatchService service : entry.getValue()) {
            service.executeAsync();
        }
        entry.getKey().whenComplete((res, e) -> {
            handle(voidPromise, slots, entry.getKey());
        });
    }
    for (Map.Entry<MasterSlaveEntry, Entry> e : commands.entrySet()) {
        RedisCommonBatchExecutor executor = new RedisCommonBatchExecutor(new NodeSource(e.getKey()), voidPromise, connectionManager, this.options, e.getValue(), slots, referenceType, false);
        executor.execute();
    }
    return promise;
}
Also used : 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) MasterSlaveEntry(org.redisson.connection.MasterSlaveEntry) RFuture(org.redisson.api.RFuture) AtomicInteger(java.util.concurrent.atomic.AtomicInteger)

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