package com.lambdaworks.redis; import java.io.Serializable; import com.lambdaworks.redis.internal.LettuceAssert; /** * Client Options to control the behavior of {@link RedisClient}. * * @author Mark Paluch */ public class ClientOptions implements Serializable { public static final boolean DEFAULT_PING_BEFORE_ACTIVATE_CONNECTION = false; public static final boolean DEFAULT_AUTO_RECONNECT = true; public static final boolean DEFAULT_CANCEL_CMD_RECONNECT_FAIL = false; public static final boolean DEFAULT_SUSPEND_RECONNECT_PROTO_FAIL = false; public static final int DEFAULT_REQUEST_QUEUE_SIZE = Integer.MAX_VALUE; public static final DisconnectedBehavior DEFAULT_DISCONNECTED_BEHAVIOR = DisconnectedBehavior.DEFAULT; public static final SocketOptions DEFAULT_SOCKET_OPTIONS = SocketOptions.create(); public static final SslOptions DEFAULT_SSL_OPTIONS = SslOptions.create(); private final boolean pingBeforeActivateConnection; private final boolean autoReconnect; private final boolean cancelCommandsOnReconnectFailure; private final boolean suspendReconnectOnProtocolFailure; private final int requestQueueSize; private final DisconnectedBehavior disconnectedBehavior; private final SocketOptions socketOptions; private final SslOptions sslOptions; protected ClientOptions(Builder builder) { pingBeforeActivateConnection = builder.pingBeforeActivateConnection; cancelCommandsOnReconnectFailure = builder.cancelCommandsOnReconnectFailure; autoReconnect = builder.autoReconnect; suspendReconnectOnProtocolFailure = builder.suspendReconnectOnProtocolFailure; requestQueueSize = builder.requestQueueSize; disconnectedBehavior = builder.disconnectedBehavior; socketOptions = builder.socketOptions; sslOptions = builder.sslOptions; } protected ClientOptions(ClientOptions original) { this.pingBeforeActivateConnection = original.isPingBeforeActivateConnection(); this.autoReconnect = original.isAutoReconnect(); this.cancelCommandsOnReconnectFailure = original.isCancelCommandsOnReconnectFailure(); this.suspendReconnectOnProtocolFailure = original.isSuspendReconnectOnProtocolFailure(); this.requestQueueSize = original.getRequestQueueSize(); this.disconnectedBehavior = original.getDisconnectedBehavior(); this.socketOptions = original.getSocketOptions(); this.sslOptions = original.getSslOptions(); } /** * Create a copy of {@literal options} * * @param options the original * @return A new instance of {@link ClientOptions} containing the values of {@literal options} */ public static ClientOptions copyOf(ClientOptions options) { return new ClientOptions(options); } /** * Returns a new {@link ClientOptions.Builder} to construct {@link ClientOptions}. * * @return a new {@link ClientOptions.Builder} to construct {@link ClientOptions}. */ public static ClientOptions.Builder builder() { return new ClientOptions.Builder(); } /** * Create a new instance of {@link ClientOptions} with default settings. * * @return a new instance of {@link ClientOptions} with default settings */ public static ClientOptions create() { return builder().build(); } /** * Builder for {@link ClientOptions}. */ public static class Builder { private boolean pingBeforeActivateConnection = DEFAULT_PING_BEFORE_ACTIVATE_CONNECTION; private boolean autoReconnect = DEFAULT_AUTO_RECONNECT; private boolean cancelCommandsOnReconnectFailure = DEFAULT_CANCEL_CMD_RECONNECT_FAIL; private boolean suspendReconnectOnProtocolFailure = DEFAULT_SUSPEND_RECONNECT_PROTO_FAIL; private int requestQueueSize = DEFAULT_REQUEST_QUEUE_SIZE; private DisconnectedBehavior disconnectedBehavior = DEFAULT_DISCONNECTED_BEHAVIOR; private SocketOptions socketOptions = DEFAULT_SOCKET_OPTIONS; private SslOptions sslOptions = DEFAULT_SSL_OPTIONS; /** * @deprecated Use {@link ClientOptions#builder()} */ @Deprecated public Builder() { } /** * Sets the {@literal PING} before activate connection flag. Defaults to {@literal false}. See * {@link #DEFAULT_PING_BEFORE_ACTIVATE_CONNECTION}. * * @param pingBeforeActivateConnection true/false * @return {@code this} */ public Builder pingBeforeActivateConnection(boolean pingBeforeActivateConnection) { this.pingBeforeActivateConnection = pingBeforeActivateConnection; return this; } /** * Enables or disables auto reconnection on connection loss. Defaults to {@literal true}. See * {@link #DEFAULT_AUTO_RECONNECT}. * * @param autoReconnect true/false * @return {@code this} */ public Builder autoReconnect(boolean autoReconnect) { this.autoReconnect = autoReconnect; return this; } /** * Suspends reconnect when reconnects run into protocol failures (SSL verification, PING before connect fails). Defaults * to {@literal false}. See {@link #DEFAULT_SUSPEND_RECONNECT_PROTO_FAIL}. * * @param suspendReconnectOnProtocolFailure true/false * @return {@code this} */ public Builder suspendReconnectOnProtocolFailure(boolean suspendReconnectOnProtocolFailure) { this.suspendReconnectOnProtocolFailure = suspendReconnectOnProtocolFailure; return this; } /** * Allows cancelling queued commands in case a reconnect fails.Defaults to {@literal false}. See * {@link #DEFAULT_CANCEL_CMD_RECONNECT_FAIL}. * * @param cancelCommandsOnReconnectFailure true/false * @return {@code this} */ public Builder cancelCommandsOnReconnectFailure(boolean cancelCommandsOnReconnectFailure) { this.cancelCommandsOnReconnectFailure = cancelCommandsOnReconnectFailure; return this; } /** * Set the per-connection request queue size. The command invocation will lead to a {@link RedisException} if the queue * size is exceeded. Setting the {@code requestQueueSize} to a lower value will lead earlier to exceptions during * overload or while the connection is in a disconnected state. A higher value means hitting the boundary will take * longer to occur, but more requests will potentially be queued up and more heap space is used. Defaults to * {@link Integer#MAX_VALUE}. See {@link #DEFAULT_REQUEST_QUEUE_SIZE}. * * @param requestQueueSize the queue size. * @return {@code this} */ public Builder requestQueueSize(int requestQueueSize) { this.requestQueueSize = requestQueueSize; return this; } /** * Sets the behavior for command invocation when connections are in a disconnected state. Defaults to {@literal true}. * See {@link #DEFAULT_DISCONNECTED_BEHAVIOR}. * * @param disconnectedBehavior must not be {@literal null}. * @return {@code this} */ public Builder disconnectedBehavior(DisconnectedBehavior disconnectedBehavior) { LettuceAssert.notNull(disconnectedBehavior, "DisconnectedBehavior must not be null"); this.disconnectedBehavior = disconnectedBehavior; return this; } /** * Sets the low-level {@link SocketOptions} for the connections kept to Redis servers. See * {@link #DEFAULT_SOCKET_OPTIONS}. * * @param socketOptions must not be {@literal null}. * @return {@code this} */ public Builder socketOptions(SocketOptions socketOptions) { LettuceAssert.notNull(socketOptions, "SocketOptions must not be null"); this.socketOptions = socketOptions; return this; } /** * Sets the {@link SslOptions} for SSL connections kept to Redis servers. See {@link #DEFAULT_SSL_OPTIONS}. * * @param sslOptions must not be {@literal null}. * @return {@code this} */ public Builder sslOptions(SslOptions sslOptions) { LettuceAssert.notNull(sslOptions, "SslOptions must not be null"); this.sslOptions = sslOptions; return this; } /** * Create a new instance of {@link ClientOptions}. * * @return new instance of {@link ClientOptions} */ public ClientOptions build() { return new ClientOptions(this); } } /** * Enables initial {@literal PING} barrier before any connection is usable. If {@literal true} (default is {@literal false} * ), every connection and reconnect will issue a {@literal PING} command and awaits its response before the connection is * activated and enabled for use. If the check fails, the connect/reconnect is treated as failure. * * @return {@literal true} if {@literal PING} barrier is enabled. */ public boolean isPingBeforeActivateConnection() { return pingBeforeActivateConnection; } /** * Controls auto-reconnect behavior on connections. If auto-reconnect is {@literal true} (default), it is enabled. As soon * as a connection gets closed/reset without the intention to close it, the client will try to reconnect and re-issue any * queued commands. * * This flag has also the effect that disconnected connections will refuse commands and cancel these with an exception. * * @return {@literal true} if auto-reconnect is enabled. */ public boolean isAutoReconnect() { return autoReconnect; } /** * If this flag is {@literal true} any queued commands will be canceled when a reconnect fails within the activation * sequence. Default is {@literal false}. * * @return {@literal true} if commands should be cancelled on reconnect failures. */ public boolean isCancelCommandsOnReconnectFailure() { return cancelCommandsOnReconnectFailure; } /** * If this flag is {@literal true} the reconnect will be suspended on protocol errors. Protocol errors are errors while SSL * negotiation or when PING before connect fails. * * @return {@literal true} if reconnect will be suspended on protocol errors. */ public boolean isSuspendReconnectOnProtocolFailure() { return suspendReconnectOnProtocolFailure; } /** * Request queue size for a connection. This value applies per connection. The command invocation will throw a * {@link RedisException} if the queue size is exceeded and a new command is requested. Defaults to * {@link Integer#MAX_VALUE}. * * @return the request queue size. */ public int getRequestQueueSize() { return requestQueueSize; } /** * Behavior for command invocation when connections are in a disconnected state. Defaults to * {@link DisconnectedBehavior#DEFAULT true}. See {@link #DEFAULT_DISCONNECTED_BEHAVIOR}. * * @return the behavior for command invocation when connections are in a disconnected state */ public DisconnectedBehavior getDisconnectedBehavior() { return disconnectedBehavior; } /** * Returns the {@link SocketOptions}. * * @return the {@link SocketOptions}. */ public SocketOptions getSocketOptions() { return socketOptions; } /** * Returns the {@link SslOptions}. * * @return the {@link SslOptions}. */ public SslOptions getSslOptions() { return sslOptions; } /** * Behavior of connections in disconnected state. */ public enum DisconnectedBehavior { /** * Accept commands when auto-reconnect is enabled, reject commands when auto-reconnect is disabled. */ DEFAULT, /** * Accept commands in disconnected state. */ ACCEPT_COMMANDS, /** * Reject commands in disconnected state. */ REJECT_COMMANDS, } }