
io.lettuce.core.cluster.NodeSelectionInvocationHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of lettuce-core Show documentation
Show all versions of lettuce-core Show documentation
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.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.reactivestreams.Publisher;
import io.lettuce.core.RedisCommandExecutionException;
import io.lettuce.core.RedisCommandTimeoutException;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.cluster.api.NodeSelectionSupport;
import io.lettuce.core.cluster.models.partitions.RedisClusterNode;
import io.lettuce.core.internal.AbstractInvocationHandler;
import io.lettuce.core.internal.ExceptionFactory;
import io.lettuce.core.internal.Futures;
import io.lettuce.core.internal.LettuceAssert;
import io.lettuce.core.internal.TimeoutProvider;
import io.lettuce.core.output.CommandOutput;
import io.lettuce.core.protocol.RedisCommand;
/**
* Invocation handler to trigger commands on multiple connections and return a holder for the values.
*
* @author Mark Paluch
* @since 4.4
*/
class NodeSelectionInvocationHandler extends AbstractInvocationHandler {
private static final Method NULL_MARKER_METHOD;
private final Map nodeSelectionMethods = new ConcurrentHashMap<>();
private final Map connectionMethod = new ConcurrentHashMap<>();
private final Class> commandsInterface;
private final AbstractNodeSelection, ?, ?, ?> selection;
private final ExecutionModel executionModel;
private final TimeoutProvider timeoutProvider;
static {
try {
NULL_MARKER_METHOD = NodeSelectionInvocationHandler.class.getDeclaredMethod("handleInvocation", Object.class,
Method.class, Object[].class);
} catch (NoSuchMethodException e) {
throw new IllegalStateException(e);
}
}
NodeSelectionInvocationHandler(AbstractNodeSelection, ?, ?, ?> selection, Class> commandsInterface,
ExecutionModel executionModel) {
this(selection, commandsInterface, null, executionModel);
}
NodeSelectionInvocationHandler(AbstractNodeSelection, ?, ?, ?> selection, Class> commandsInterface,
TimeoutProvider timeoutProvider) {
this(selection, commandsInterface, timeoutProvider, ExecutionModel.SYNC);
}
private NodeSelectionInvocationHandler(AbstractNodeSelection, ?, ?, ?> selection, Class> commandsInterface,
TimeoutProvider timeoutProvider, ExecutionModel executionModel) {
if (executionModel == ExecutionModel.SYNC) {
LettuceAssert.notNull(timeoutProvider, "TimeoutProvider must not be null");
}
LettuceAssert.notNull(executionModel, "ExecutionModel must not be null");
this.selection = selection;
this.commandsInterface = commandsInterface;
this.timeoutProvider = timeoutProvider;
this.executionModel = executionModel;
}
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
protected Object handleInvocation(Object proxy, Method method, Object[] args) throws Throwable {
try {
if (method.getName().equals("commands") && args.length == 0) {
return proxy;
}
Method targetMethod = findMethod(commandsInterface, method, connectionMethod);
if (targetMethod == null) {
Method nodeSelectionMethod = findMethod(NodeSelectionSupport.class, method, nodeSelectionMethods);
return nodeSelectionMethod.invoke(selection, args);
}
Map>> connections = new LinkedHashMap<>(
selection.size(), 1);
connections.putAll(selection.statefulMap());
Map executions = new LinkedHashMap<>(selection.size(), 1);
AtomicLong timeout = new AtomicLong();
for (Map.Entry>> entry : connections
.entrySet()) {
CompletableFuture extends StatefulRedisConnection, ?>> connection = entry.getValue();
CompletableFuture
© 2015 - 2025 Weber Informatics LLC | Privacy Policy