package com.lambdaworks.redis;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import com.lambdaworks.redis.internal.LettuceAssert;
import com.lambdaworks.redis.protocol.CommandEncoder;
import com.lambdaworks.redis.protocol.CommandHandler;
import com.lambdaworks.redis.protocol.ConnectionWatchdog;
import com.lambdaworks.redis.protocol.ReconnectionListener;
import com.lambdaworks.redis.resource.ClientResources;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.util.Timer;
import io.netty.util.concurrent.EventExecutorGroup;
/**
* Connection builder for connections. This class is part of the internal API.
*
* @author Mark Paluch
*/
public class ConnectionBuilder {
private Supplier<SocketAddress> socketAddressSupplier;
private ConnectionEvents connectionEvents;
private RedisChannelHandler<?, ?> connection;
private CommandHandler<?, ?> commandHandler;
private ChannelGroup channelGroup;
private Timer timer;
private Bootstrap bootstrap;
private ClientOptions clientOptions;
private EventExecutorGroup workerPool;
private long timeout;
private TimeUnit timeUnit;
private ClientResources clientResources;
private char[] password;
private ReconnectionListener reconnectionListener = ReconnectionListener.NO_OP;
public static ConnectionBuilder connectionBuilder() {
return new ConnectionBuilder();
}
protected List<ChannelHandler> buildHandlers() {
LettuceAssert.assertState(channelGroup != null, "ChannelGroup must be set");
LettuceAssert.assertState(connectionEvents != null, "ConnectionEvents must be set");
LettuceAssert.assertState(connection != null, "Connection must be set");
LettuceAssert.assertState(clientResources != null, "ClientResources must be set");
List<ChannelHandler> handlers = new ArrayList<>();
connection.setOptions(clientOptions);
handlers.add(new ChannelGroupListener(channelGroup));
handlers.add(new CommandEncoder());
handlers.add(commandHandler);
handlers.add(connection);
handlers.add(new ConnectionEventTrigger(connectionEvents, connection, clientResources.eventBus()));
if (clientOptions.isAutoReconnect()) {
handlers.add(createConnectionWatchdog());
}
return handlers;
}
protected ConnectionWatchdog createConnectionWatchdog() {
LettuceAssert.assertState(bootstrap != null, "Bootstrap must be set for autoReconnect=true");
LettuceAssert.assertState(timer != null, "Timer must be set for autoReconnect=true");
LettuceAssert.assertState(socketAddressSupplier != null, "SocketAddressSupplier must be set for autoReconnect=true");
ConnectionWatchdog watchdog = new ConnectionWatchdog(clientResources.reconnectDelay(), clientOptions, bootstrap, timer,
workerPool, socketAddressSupplier, reconnectionListener);
watchdog.setListenOnChannelInactive(true);
return watchdog;
}
public RedisChannelInitializer build() {
return new PlainChannelInitializer(clientOptions.isPingBeforeActivateConnection(), password(), buildHandlers(),
clientResources.eventBus());
}
public ConnectionBuilder socketAddressSupplier(Supplier<SocketAddress> socketAddressSupplier) {
this.socketAddressSupplier = socketAddressSupplier;
return this;
}
public SocketAddress socketAddress() {
LettuceAssert.assertState(socketAddressSupplier != null, "SocketAddressSupplier must be set");
return socketAddressSupplier.get();
}
public ConnectionBuilder timeout(long timeout, TimeUnit timeUnit) {
this.timeout = timeout;
this.timeUnit = timeUnit;
return this;
}
public long getTimeout() {
return timeout;
}
public TimeUnit getTimeUnit() {
return timeUnit;
}
public ConnectionBuilder reconnectionListener(ReconnectionListener reconnectionListener) {
LettuceAssert.notNull(reconnectionListener, "ReconnectionListener must not be null");
this.reconnectionListener = reconnectionListener;
return this;
}
public ConnectionBuilder clientOptions(ClientOptions clientOptions) {
this.clientOptions = clientOptions;
return this;
}
public ConnectionBuilder workerPool(EventExecutorGroup workerPool) {
this.workerPool = workerPool;
return this;
}
public ConnectionBuilder connectionEvents(ConnectionEvents connectionEvents) {
this.connectionEvents = connectionEvents;
return this;
}
public ConnectionBuilder connection(RedisChannelHandler<?, ?> connection) {
this.connection = connection;
return this;
}
public ConnectionBuilder channelGroup(ChannelGroup channelGroup) {
this.channelGroup = channelGroup;
return this;
}
public ConnectionBuilder commandHandler(CommandHandler<?, ?> commandHandler) {
this.commandHandler = commandHandler;
return this;
}
public ConnectionBuilder timer(Timer timer) {
this.timer = timer;
return this;
}
public ConnectionBuilder bootstrap(Bootstrap bootstrap) {
this.bootstrap = bootstrap;
return this;
}
public ConnectionBuilder clientResources(ClientResources clientResources) {
this.clientResources = clientResources;
return this;
}
public ConnectionBuilder password(char[] password) {
this.password = password;
return this;
}
public RedisChannelHandler<?, ?> connection() {
return connection;
}
public CommandHandler<?, ?> commandHandler() {
return commandHandler;
}
public Bootstrap bootstrap() {
return bootstrap;
}
public ClientOptions clientOptions() {
return clientOptions;
}
public ClientResources clientResources() {
return clientResources;
}
public char[] password() {
return password;
}
public EventExecutorGroup workerPool() {
return workerPool;
}
}