All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.lettuce.core.cluster.MultiNodeExecution Maven / Gradle / Ivy

Go to download

Advanced and thread-safe Java Redis client for synchronous, asynchronous, and reactive usage. Supports Cluster, Sentinel, Pipelining, Auto-Reconnect, Codecs and much more.

The newest version!
/*
 * Copyright 2011-Present, Redis Ltd. and Contributors
 * All rights reserved.
 *
 * Licensed under the MIT License.
 *
 * This file contains contributions from third-party contributors
 * licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.lettuce.core.cluster;

import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicLong;

import io.lettuce.core.RedisCommandInterruptedException;
import io.lettuce.core.RedisFuture;
import io.lettuce.core.internal.Exceptions;

/**
 * Utility to perform and synchronize command executions on multiple cluster nodes.
 *
 * @author Mark Paluch
 */
public class MultiNodeExecution {

    public static  T execute(Callable function) {
        try {
            return function.call();
        } catch (Exception e) {
            throw Exceptions.bubble(e);
        }
    }

    /**
     * Aggregate (sum) results of the {@link RedisFuture}s.
     *
     * @param executions mapping of a key to the future
     * @return future producing an aggregation result
     */
    public static RedisFuture aggregateAsync(Map> executions) {

        return new PipelinedRedisFuture<>(executions, objectPipelinedRedisFuture -> {
            AtomicLong result = new AtomicLong();
            for (CompletionStage future : executions.values()) {
                Long value = execute(() -> future.toCompletableFuture().get());
                if (value != null) {
                    result.getAndAdd(value);
                }
            }

            return result.get();
        });
    }

    /**
     * Returns the result of the first {@link RedisFuture} and guarantee that all futures are finished.
     *
     * @param executions mapping of a key to the future
     * @param  result type
     * @return future returning the first result.
     */
    public static  RedisFuture firstOfAsync(Map> executions) {

        return new PipelinedRedisFuture<>(executions, objectPipelinedRedisFuture -> {
            // make sure, that all futures are executed before returning the result.
            for (CompletionStage future : executions.values()) {
                execute(() -> future.toCompletableFuture().get());
            }
            for (CompletionStage future : executions.values()) {
                return execute(() -> future.toCompletableFuture().get());
            }
            return null;
        });
    }

    /**
     * Returns the result of the last {@link RedisFuture} and guarantee that all futures are finished.
     *
     * @param executions mapping of a key to the future
     * @param  result type
     * @return future returning the first result.
     */
    public static  RedisFuture lastOfAsync(Map> executions) {

        return new PipelinedRedisFuture<>(executions, objectPipelinedRedisFuture -> {
            // make sure, that all futures are executed before returning the result.
            T result = null;
            for (CompletionStage future : executions.values()) {
                result = execute(() -> future.toCompletableFuture().get());
            }
            return result;
        });
    }

    /**
     * Returns always {@literal OK} and guarantee that all futures are finished.
     *
     * @param executions mapping of a key to the future
     * @return future returning the first result.
     */
    public static RedisFuture alwaysOkOfAsync(Map> executions) {

        return new PipelinedRedisFuture<>(executions, objectPipelinedRedisFuture -> {

            synchronize(executions);

            return "OK";
        });
    }

    private static void synchronize(Map> executions) {

        // make sure, that all futures are executed before returning the result.
        for (CompletionStage future : executions.values()) {
            try {
                future.toCompletableFuture().get();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RedisCommandInterruptedException(e);
            } catch (ExecutionException e) {
                // swallow exceptions
            }
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy