com.lambdaworks.redis.cluster.ClusterTopologyRefreshOptions Maven / Gradle / Ivy
/*
* Copyright 2011-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.lambdaworks.redis.cluster;
import java.util.*;
import java.util.concurrent.TimeUnit;
import com.lambdaworks.redis.internal.LettuceAssert;
/**
* Options to control the Cluster topology refreshing of {@link RedisClusterClient}.
*
* @author Mark Paluch
* @since 4.2
*/
public class ClusterTopologyRefreshOptions {
public static final boolean DEFAULT_PERIODIC_REFRESH_ENABLED = false;
public static final long DEFAULT_REFRESH_PERIOD = 60;
public static final TimeUnit DEFAULT_REFRESH_PERIOD_UNIT = TimeUnit.SECONDS;
public static final boolean DEFAULT_DYNAMIC_REFRESH_SOURCES = true;
public static final Set DEFAULT_ADAPTIVE_REFRESH_TRIGGERS = Collections.emptySet();
public static final long DEFAULT_ADAPTIVE_REFRESH_TIMEOUT = 30;
public static final TimeUnit DEFAULT_ADAPTIVE_REFRESH_TIMEOUT_UNIT = TimeUnit.SECONDS;
public static final int DEFAULT_REFRESH_TRIGGERS_RECONNECT_ATTEMPTS = 5;
public static final boolean DEFAULT_CLOSE_STALE_CONNECTIONS = true;
private final boolean periodicRefreshEnabled;
private final long refreshPeriod;
private final TimeUnit refreshPeriodUnit;
private final boolean closeStaleConnections;
private final boolean dynamicRefreshSources;
private final Set adaptiveRefreshTriggers;
private final long adaptiveRefreshTimeout;
private final TimeUnit adaptiveRefreshTimeoutUnit;
private final int refreshTriggersReconnectAttempts;
protected ClusterTopologyRefreshOptions(Builder builder) {
this.periodicRefreshEnabled = builder.periodicRefreshEnabled;
this.refreshPeriod = builder.refreshPeriod;
this.refreshPeriodUnit = builder.refreshPeriodUnit;
this.closeStaleConnections = builder.closeStaleConnections;
this.dynamicRefreshSources = builder.dynamicRefreshSources;
this.adaptiveRefreshTriggers = Collections.unmodifiableSet(new HashSet<>(builder.adaptiveRefreshTriggers));
this.adaptiveRefreshTimeout = builder.adaptiveRefreshTimeout;
this.adaptiveRefreshTimeoutUnit = builder.adaptiveRefreshTimeoutUnit;
this.refreshTriggersReconnectAttempts = builder.refreshTriggersReconnectAttempts;
}
protected ClusterTopologyRefreshOptions(ClusterTopologyRefreshOptions original) {
this.periodicRefreshEnabled = original.periodicRefreshEnabled;
this.refreshPeriod = original.refreshPeriod;
this.refreshPeriodUnit = original.refreshPeriodUnit;
this.closeStaleConnections = original.closeStaleConnections;
this.dynamicRefreshSources = original.dynamicRefreshSources;
this.adaptiveRefreshTriggers = Collections.unmodifiableSet(new HashSet<>(original.adaptiveRefreshTriggers));
this.adaptiveRefreshTimeout = original.adaptiveRefreshTimeout;
this.adaptiveRefreshTimeoutUnit = original.adaptiveRefreshTimeoutUnit;
this.refreshTriggersReconnectAttempts = original.refreshTriggersReconnectAttempts;
}
/**
* Create a copy of {@literal options}.
*
* @param options the original
* @return A new instance of {@link ClusterTopologyRefreshOptions} containing the values of {@literal options}
*/
public static ClusterTopologyRefreshOptions copyOf(ClusterTopologyRefreshOptions options) {
return new ClusterTopologyRefreshOptions(options);
}
/**
* Returns a new {@link ClusterTopologyRefreshOptions.Builder} to construct {@link ClusterTopologyRefreshOptions}.
*
* @return a new {@link ClusterTopologyRefreshOptions.Builder} to construct {@link ClusterTopologyRefreshOptions}.
*/
public static ClusterTopologyRefreshOptions.Builder builder() {
return new ClusterTopologyRefreshOptions.Builder();
}
/**
* Create a new {@link ClusterTopologyRefreshOptions} using default settings.
*
* @return a new instance of default cluster client client options.
*/
public static ClusterTopologyRefreshOptions create() {
return builder().build();
}
/**
* Create a new {@link ClusterTopologyRefreshOptions} using default settings with enabled periodic and adaptive refresh.
*
* @return a new instance of default cluster client client options.
*/
public static ClusterTopologyRefreshOptions enabled() {
return builder().enablePeriodicRefresh().enableAllAdaptiveRefreshTriggers().build();
}
/**
* Builder for {@link ClusterTopologyRefreshOptions}.
*/
public static class Builder {
private boolean periodicRefreshEnabled = DEFAULT_PERIODIC_REFRESH_ENABLED;
private long refreshPeriod = DEFAULT_REFRESH_PERIOD;
private TimeUnit refreshPeriodUnit = DEFAULT_REFRESH_PERIOD_UNIT;
private boolean closeStaleConnections = DEFAULT_CLOSE_STALE_CONNECTIONS;
private boolean dynamicRefreshSources = DEFAULT_DYNAMIC_REFRESH_SOURCES;
private Set adaptiveRefreshTriggers = new HashSet<>(DEFAULT_ADAPTIVE_REFRESH_TRIGGERS);
private long adaptiveRefreshTimeout = DEFAULT_ADAPTIVE_REFRESH_TIMEOUT;
private TimeUnit adaptiveRefreshTimeoutUnit = DEFAULT_ADAPTIVE_REFRESH_TIMEOUT_UNIT;
private int refreshTriggersReconnectAttempts = DEFAULT_REFRESH_TRIGGERS_RECONNECT_ATTEMPTS;
private Builder() {
}
/**
* Enables periodic cluster topology updates. The client starts updating the cluster topology in the intervals of
* {@link Builder#refreshPeriod}. Defaults to {@literal false}. See {@link #DEFAULT_PERIODIC_REFRESH_ENABLED}.
*
* @return {@code this}
*/
public Builder enablePeriodicRefresh() {
return enablePeriodicRefresh(true);
}
/**
* Enable regular cluster topology updates. The client starts updating the cluster topology in the intervals of
* {@link Builder#refreshPeriod}. Defaults to {@literal false}. See {@link #DEFAULT_PERIODIC_REFRESH_ENABLED}.
*
* @param enabled {@literal true} enable regular cluster topology updates or {@literal false} to disable auto-updating
* @return {@code this}
*/
public Builder enablePeriodicRefresh(boolean enabled) {
this.periodicRefreshEnabled = enabled;
return this;
}
/**
* Enables periodic refresh and sets the refresh period. Defaults to {@literal 60 SECONDS}. See
* {@link #DEFAULT_REFRESH_PERIOD} and {@link #DEFAULT_REFRESH_PERIOD_UNIT}. This method is a shortcut for
* {@link #refreshPeriod(long, TimeUnit)} and {@link #enablePeriodicRefresh()}.
*
* @param refreshPeriod period for triggering topology updates, must be greater {@literal 0}
* @param refreshPeriodUnit unit for {@code refreshPeriod}, must not be {@literal null}
* @return {@code this}
*/
public Builder enablePeriodicRefresh(long refreshPeriod, TimeUnit refreshPeriodUnit) {
return refreshPeriod(refreshPeriod, refreshPeriodUnit).enablePeriodicRefresh();
}
/**
* Set the refresh period. Defaults to {@literal 60 SECONDS}. See {@link #DEFAULT_REFRESH_PERIOD} and
* {@link #DEFAULT_REFRESH_PERIOD_UNIT}.
*
* @param refreshPeriod period for triggering topology updates, must be greater {@literal 0}
* @param refreshPeriodUnit unit for {@code refreshPeriod}, must not be {@literal null}
* @return {@code this}
*/
public Builder refreshPeriod(long refreshPeriod, TimeUnit refreshPeriodUnit) {
LettuceAssert.isTrue(refreshPeriod > 0, "RefreshPeriod must be greater 0");
LettuceAssert.notNull(refreshPeriodUnit, "TimeUnit must not be null");
this.refreshPeriod = refreshPeriod;
this.refreshPeriodUnit = refreshPeriodUnit;
return this;
}
/**
* Flag, whether to close stale connections when refreshing the cluster topology. Defaults to {@literal true}. Comes
* only into effect if {@link #isPeriodicRefreshEnabled()} is {@literal true}. See
* {@link ClusterTopologyRefreshOptions#DEFAULT_CLOSE_STALE_CONNECTIONS}.
*
* @param closeStaleConnections {@literal true} if stale connections are cleaned up after cluster topology updates
* @return {@code this}
*/
public Builder closeStaleConnections(boolean closeStaleConnections) {
this.closeStaleConnections = closeStaleConnections;
return this;
}
/**
* Discover cluster nodes from topology and use the discovered nodes as source for the cluster topology. Using dynamic
* refresh will query all discovered nodes for the cluster topology and calculate the number of clients for each node.If
* set to {@literal false}, only the initial seed nodes will be used as sources for topology discovery and the number of
* clients will be obtained only for the initial seed nodes. This can be useful when using Redis Cluster with many
* nodes. Defaults to {@literal true}. See {@link ClusterTopologyRefreshOptions#DEFAULT_DYNAMIC_REFRESH_SOURCES}.
*
* @param dynamicRefreshSources {@literal true} to discover and query all cluster nodes for obtaining the cluster
* topology
* @return {@code this}
*/
public Builder dynamicRefreshSources(boolean dynamicRefreshSources) {
this.dynamicRefreshSources = dynamicRefreshSources;
return this;
}
/**
* Enables adaptive topology refreshing using one or more {@link RefreshTrigger triggers}. Adaptive refresh triggers
* initiate topology view updates based on events happened during Redis Cluster operations. Adaptive triggers lead to an
* immediate topology refresh. Adaptive triggered refreshes are rate-limited using a timeout since events can happen on
* a large scale. Adaptive refresh triggers are disabled by default. See also
* {@link #adaptiveRefreshTriggersTimeout(long, TimeUnit)} and {@link RefreshTrigger}.
*
* @param refreshTrigger one or more {@link RefreshTrigger} to enabled
* @return {@code this}
*/
public Builder enableAdaptiveRefreshTrigger(RefreshTrigger... refreshTrigger) {
LettuceAssert.notNull(refreshTrigger, "RefreshTriggers must not be null");
LettuceAssert.noNullElements(refreshTrigger, "RefreshTriggers must not contain null elements");
adaptiveRefreshTriggers.addAll(Arrays.asList(refreshTrigger));
return this;
}
/**
* Enables adaptive topology refreshing using all {@link RefreshTrigger triggers}. Adaptive refresh triggers initiate
* topology view updates based on events happened during Redis Cluster operations. Adaptive triggers lead to an
* immediate topology refresh. Adaptive triggered refreshes are rate-limited using a timeout since events can happen on
* a large scale. Adaptive refresh triggers are disabled by default. See also
* {@link #adaptiveRefreshTriggersTimeout(long, TimeUnit)} and {@link RefreshTrigger}.
*
* @return {@code this}
*/
public Builder enableAllAdaptiveRefreshTriggers() {
adaptiveRefreshTriggers.addAll(EnumSet.allOf(RefreshTrigger.class));
return this;
}
/**
* Set the timeout for adaptive topology updates. This timeout is to rate-limit topology updates initiated by refresh
* triggers to one topology refresh per timeout. Defaults to {@literal 30 SECONDS}. See {@link #DEFAULT_REFRESH_PERIOD}
* and {@link #DEFAULT_REFRESH_PERIOD_UNIT}.
*
* @param timeout timeout for rate-limit adaptive topology updates
* @param unit unit for {@code timeout}
* @return {@code this}
*/
public Builder adaptiveRefreshTriggersTimeout(long timeout, TimeUnit unit) {
this.adaptiveRefreshTimeout = timeout;
this.adaptiveRefreshTimeoutUnit = unit;
return this;
}
/**
* Set the threshold for the {@link RefreshTrigger#PERSISTENT_RECONNECTS}. Topology updates based on persistent
* reconnects lead only to a refresh if the reconnect process tries at least {@code refreshTriggersReconnectAttempts}.
* See {@link #DEFAULT_REFRESH_TRIGGERS_RECONNECT_ATTEMPTS}.
*
* @param refreshTriggersReconnectAttempts number of reconnect attempts for a connection before a n adaptive topology
* refresh is triggered
* @return {@code this}
*/
public Builder refreshTriggersReconnectAttempts(int refreshTriggersReconnectAttempts) {
this.refreshTriggersReconnectAttempts = refreshTriggersReconnectAttempts;
return this;
}
/**
* Create a new instance of {@link ClusterTopologyRefreshOptions}
*
* @return new instance of {@link ClusterTopologyRefreshOptions}
*/
public ClusterTopologyRefreshOptions build() {
return new ClusterTopologyRefreshOptions(this);
}
}
/**
* Flag, whether regular cluster topology updates are updated. The client starts updating the cluster topology in the
* intervals of {@link #getRefreshPeriod()} /{@link #getRefreshPeriodUnit()}. Defaults to {@literal false}.
*
* @return {@literal true} it the cluster topology view is updated periodically
*/
public boolean isPeriodicRefreshEnabled() {
return periodicRefreshEnabled;
}
/**
* Period between the regular cluster topology updates. Defaults to {@literal 60}.
*
* @return the period between the regular cluster topology updates
*/
public long getRefreshPeriod() {
return refreshPeriod;
}
/**
* Unit for the {@link #getRefreshPeriod()}. Defaults to {@link TimeUnit#SECONDS}.
*
* @return unit for the {@link #getRefreshPeriod()}
*/
public TimeUnit getRefreshPeriodUnit() {
return refreshPeriodUnit;
}
/**
* Flag, whether to close stale connections when refreshing the cluster topology. Defaults to {@literal true}. Comes only
* into effect if {@link #isPeriodicRefreshEnabled()} is {@literal true}.
*
* @return {@literal true} if stale connections are cleaned up after cluster topology updates
*/
public boolean isCloseStaleConnections() {
return closeStaleConnections;
}
/**
* Discover cluster nodes from topology and use the discovered nodes as source for the cluster topology. Using dynamic
* refresh will query all discovered nodes for the cluster topology and calculate the number of clients for each node.If set
* to {@literal false}, only the initial seed nodes will be used as sources for topology discovery and the number of clients
* will be obtained only for the initial seed nodes. This can be useful when using Redis Cluster with many nodes.
*
* @return {@link true} if dynamic refresh sources are enabled
*/
public boolean useDynamicRefreshSources() {
return dynamicRefreshSources;
}
/**
* Returns the set of {@link RefreshTrigger triggers}. Adaptive refresh triggers initiate topology view updates based on
* events happened during Redis Cluster operations. Adaptive triggers lead to an immediate topology refresh. Adaptive
* triggered refreshes are rate-limited using a timeout since events can happen on a large scale. Adaptive refresh triggers
* are disabled by default.
*
* @return the set of {@link RefreshTrigger triggers}
*/
public Set getAdaptiveRefreshTriggers() {
return adaptiveRefreshTriggers;
}
/**
* Timeout between adaptive cluster topology updates. Defaults to {@literal 30}.
*
* @return the period between the regular cluster topology updates
*/
public long getAdaptiveRefreshTimeout() {
return adaptiveRefreshTimeout;
}
/**
* Unit for the {@link #getAdaptiveRefreshTimeout()}. Defaults to {@link TimeUnit#SECONDS}.
*
* @return unit for the {@link #getRefreshPeriod()}
*/
public TimeUnit getAdaptiveRefreshTimeoutUnit() {
return adaptiveRefreshTimeoutUnit;
}
/**
* Threshold for {@link RefreshTrigger#PERSISTENT_RECONNECTS}. Topology updates based on persistent reconnects lead only to
* a refresh if the reconnect process tries at least {@code refreshTriggersReconnectAttempts}. See
* {@link #DEFAULT_REFRESH_TRIGGERS_RECONNECT_ATTEMPTS}.
*
* @return umber of reconnect attempts for a connection before a n adaptive topology refresh is triggered
*/
public int getRefreshTriggersReconnectAttempts() {
return refreshTriggersReconnectAttempts;
}
/**
* Available refresh triggers to signal early topology refreshing.
*/
public enum RefreshTrigger {
/**
* Redis responds with a {@code MOVED} redirection to a command.
*/
MOVED_REDIRECT,
/**
* Redis responds with a {@code ASK} redirection to a command.
*/
ASK_REDIRECT,
/**
* Connections to a particular host run into persistent reconnects (more than one attempt).
*/
PERSISTENT_RECONNECTS,
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy