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

io.lettuce.core.cluster.AsyncExecutionsImpl 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!
package io.lettuce.core.cluster;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collector;

import io.lettuce.core.cluster.api.async.AsyncExecutions;
import io.lettuce.core.cluster.models.partitions.RedisClusterNode;

/**
 * @author Mark Paluch
 */
class AsyncExecutionsImpl implements AsyncExecutions {

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private static final AtomicReferenceFieldUpdater, CompletionStage> UPDATER = (AtomicReferenceFieldUpdater) AtomicReferenceFieldUpdater
            .newUpdater(AsyncExecutionsImpl.class, CompletionStage.class, "publicStage");

    private final Map> executions;

    private volatile CompletionStage> publicStage;

    @SuppressWarnings("unchecked")
    public AsyncExecutionsImpl(Map> executions) {

        Map> map = new HashMap<>(executions);
        this.executions = Collections.unmodifiableMap((Map) map);
    }

    @Override
    public Map> asMap() {
        return executions;
    }

    @Override
    public Iterator> iterator() {
        return asMap().values().iterator();
    }

    @Override
    public Collection nodes() {
        return executions.keySet();
    }

    @Override
    public CompletableFuture get(RedisClusterNode redisClusterNode) {
        return executions.get(redisClusterNode);
    }

    @Override
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public CompletableFuture[] futures() {
        return executions.values().toArray(new CompletableFuture[0]);
    }

    @Override
    public  CompletionStage thenCollect(Collector collector) {

        return publicStage().thenApply(items -> {

            A container = collector.supplier().get();

            BiConsumer accumulator = collector.accumulator();
            items.forEach(item -> accumulator.accept(container, item));

            if (collector.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
                return (R) container;
            }

            return collector.finisher().apply(container);
        });
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private CompletionStage> publicStage() {

        CompletionStage stage = UPDATER.get(this);

        if (stage == null) {
            stage = createPublicStage(this.executions);
            UPDATER.compareAndSet(this, null, stage);
        }

        return stage;
    }

    @SuppressWarnings("rawtypes")
    private CompletableFuture> createPublicStage(Map> map) {

        return CompletableFuture.allOf(map.values().toArray(new CompletableFuture[0])).thenApply(ignore -> {

            List results = new ArrayList<>(map.size());
            for (CompletionStage value : map.values()) {
                results.add(value.toCompletableFuture().join());
            }

            return results;
        });
    }

    // --------------------------------
    // delegate methods.
    // --------------------------------

    @Override
    public  CompletionStage thenApply(Function, ? extends U> fn) {
        return publicStage().thenApply(fn);
    }

    @Override
    public  CompletionStage thenApplyAsync(Function, ? extends U> fn) {
        return publicStage().thenApplyAsync(fn);
    }

    @Override
    public  CompletionStage thenApplyAsync(Function, ? extends U> fn, Executor executor) {
        return publicStage().thenApplyAsync(fn, executor);
    }

    @Override
    public CompletionStage thenAccept(Consumer> action) {
        return publicStage().thenAccept(action);
    }

    @Override
    public CompletionStage thenAcceptAsync(Consumer> action) {
        return publicStage().thenAcceptAsync(action);
    }

    @Override
    public CompletionStage thenAcceptAsync(Consumer> action, Executor executor) {
        return publicStage().thenAcceptAsync(action, executor);
    }

    @Override
    public CompletionStage thenRun(Runnable action) {
        return publicStage().thenRun(action);
    }

    @Override
    public CompletionStage thenRunAsync(Runnable action) {
        return publicStage().thenRunAsync(action);
    }

    @Override
    public CompletionStage thenRunAsync(Runnable action, Executor executor) {
        return publicStage().thenRunAsync(action, executor);
    }

    @Override
    public  CompletionStage thenCombine(CompletionStage other,
            BiFunction, ? super U, ? extends V> fn) {
        return publicStage().thenCombine(other, fn);
    }

    @Override
    public  CompletionStage thenCombineAsync(CompletionStage other,
            BiFunction, ? super U, ? extends V> fn) {
        return publicStage().thenCombineAsync(other, fn);
    }

    @Override
    public  CompletionStage thenCombineAsync(CompletionStage other,
            BiFunction, ? super U, ? extends V> fn, Executor executor) {
        return publicStage().thenCombineAsync(other, fn, executor);
    }

    @Override
    public  CompletionStage thenAcceptBoth(CompletionStage other,
            BiConsumer, ? super U> action) {
        return publicStage().thenAcceptBoth(other, action);
    }

    @Override
    public  CompletionStage thenAcceptBothAsync(CompletionStage other,
            BiConsumer, ? super U> action) {
        return publicStage().thenAcceptBothAsync(other, action);
    }

    @Override
    public  CompletionStage thenAcceptBothAsync(CompletionStage other,
            BiConsumer, ? super U> action, Executor executor) {
        return publicStage().thenAcceptBothAsync(other, action, executor);
    }

    @Override
    public CompletionStage runAfterBoth(CompletionStage other, Runnable action) {
        return publicStage().runAfterBoth(other, action);
    }

    @Override
    public CompletionStage runAfterBothAsync(CompletionStage other, Runnable action) {
        return publicStage().runAfterBothAsync(other, action);
    }

    @Override
    public CompletionStage runAfterBothAsync(CompletionStage other, Runnable action, Executor executor) {
        return publicStage().runAfterBothAsync(other, action, executor);
    }

    @Override
    public  CompletionStage applyToEither(CompletionStage> other, Function, U> fn) {
        return publicStage().applyToEither(other, fn);
    }

    @Override
    public  CompletionStage applyToEitherAsync(CompletionStage> other,
            Function, U> fn) {
        return publicStage().applyToEitherAsync(other, fn);
    }

    @Override
    public  CompletionStage applyToEitherAsync(CompletionStage> other, Function, U> fn,
            Executor executor) {
        return publicStage().applyToEitherAsync(other, fn, executor);
    }

    @Override
    public CompletionStage acceptEither(CompletionStage> other, Consumer> action) {
        return publicStage().acceptEither(other, action);
    }

    @Override
    public CompletionStage acceptEitherAsync(CompletionStage> other, Consumer> action) {
        return publicStage().acceptEitherAsync(other, action);
    }

    @Override
    public CompletionStage acceptEitherAsync(CompletionStage> other, Consumer> action,
            Executor executor) {
        return publicStage().acceptEitherAsync(other, action, executor);
    }

    @Override
    public CompletionStage runAfterEither(CompletionStage other, Runnable action) {
        return publicStage().runAfterEither(other, action);
    }

    @Override
    public CompletionStage runAfterEitherAsync(CompletionStage other, Runnable action) {
        return publicStage().runAfterEitherAsync(other, action);
    }

    @Override
    public CompletionStage runAfterEitherAsync(CompletionStage other, Runnable action, Executor executor) {
        return publicStage().runAfterEitherAsync(other, action, executor);
    }

    @Override
    public  CompletionStage thenCompose(Function, ? extends CompletionStage> fn) {
        return publicStage().thenCompose(fn);
    }

    @Override
    public  CompletionStage thenComposeAsync(Function, ? extends CompletionStage> fn) {
        return publicStage().thenComposeAsync(fn);
    }

    @Override
    public  CompletionStage thenComposeAsync(Function, ? extends CompletionStage> fn,
            Executor executor) {
        return publicStage().thenComposeAsync(fn, executor);
    }

    @Override
    public CompletionStage> exceptionally(Function> fn) {
        return publicStage().exceptionally(fn);
    }

    @Override
    public CompletionStage> whenComplete(BiConsumer, ? super Throwable> action) {
        return publicStage().whenComplete(action);
    }

    @Override
    public CompletionStage> whenCompleteAsync(BiConsumer, ? super Throwable> action) {
        return publicStage().whenCompleteAsync(action);
    }

    @Override
    public CompletionStage> whenCompleteAsync(BiConsumer, ? super Throwable> action,
            Executor executor) {
        return publicStage().whenCompleteAsync(action, executor);
    }

    @Override
    public  CompletionStage handle(BiFunction, Throwable, ? extends U> fn) {
        return publicStage().handle(fn);
    }

    @Override
    public  CompletionStage handleAsync(BiFunction, Throwable, ? extends U> fn) {
        return publicStage().handleAsync(fn);
    }

    @Override
    public  CompletionStage handleAsync(BiFunction, Throwable, ? extends U> fn, Executor executor) {
        return publicStage().handleAsync(fn, executor);
    }

    @Override
    public CompletableFuture> toCompletableFuture() {
        return publicStage().toCompletableFuture();
    }

}