package com.lambdaworks.redis.cluster;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Function;
import java.util.function.Supplier;
import com.lambdaworks.redis.cluster.models.partitions.RedisClusterNode;
import com.lambdaworks.redis.internal.LettuceAssert;
import com.lambdaworks.redis.resource.ClientResources;
import com.lambdaworks.redis.resource.SocketAddressResolver;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
/**
* Round-Robin socket address supplier. Cluster nodes are iterated circular/infinitely.
*
* @author Mark Paluch
*/
class RoundRobinSocketAddressSupplier implements Supplier<SocketAddress> {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(RoundRobinSocketAddressSupplier.class);
private final Collection<RedisClusterNode> partitions;
private final Collection<RedisClusterNode> clusterNodes = new ArrayList<>();
private final Function<Collection<RedisClusterNode>, Collection<RedisClusterNode>> sortFunction;
private final ClientResources clientResources;
private RoundRobin<? extends RedisClusterNode> roundRobin;
public RoundRobinSocketAddressSupplier(Collection<RedisClusterNode> partitions,
Function<? extends Collection<RedisClusterNode>, Collection<RedisClusterNode>> sortFunction,
ClientResources clientResources) {
LettuceAssert.notNull(partitions, "Partitions must not be null");
LettuceAssert.notNull(sortFunction, "Sort-Function must not be null");
this.partitions = partitions;
this.clusterNodes.addAll(partitions);
this.roundRobin = new RoundRobin<>(clusterNodes);
this.sortFunction = (Function) sortFunction;
this.clientResources = clientResources;
resetRoundRobin();
}
@Override
public SocketAddress get() {
if (!clusterNodes.containsAll(partitions)) {
resetRoundRobin();
}
RedisClusterNode redisClusterNode = roundRobin.next();
return getSocketAddress(redisClusterNode);
}
protected void resetRoundRobin() {
clusterNodes.clear();
clusterNodes.addAll(sortFunction.apply(partitions));
roundRobin.offset = null;
}
protected SocketAddress getSocketAddress(RedisClusterNode redisClusterNode) {
SocketAddress resolvedAddress = SocketAddressResolver.resolve(redisClusterNode.getUri(), clientResources.dnsResolver());
logger.debug("Resolved SocketAddress {} using for Cluster node {}", resolvedAddress, redisClusterNode.getNodeId());
return resolvedAddress;
}
}