Skip to content

Commit c46a492

Browse files
atakavciggivo
andauthored
[automatic failover] Implement lag-aware api (#4235)
* - lag-aware api * - introduce healtCheckMetaConfig - add config objects for both EchoStrategy and LagAwareStrategy - make StrategySupplier interface generic - fix impacted tests * - fix issues with docs and log * Fix EchoStrategyIntegrationTest after merge * Implement resolve bdbId based on configured HostAndPort * format & merge RedisRestAPI unit tests * introduce builder for LagAwareStrategy * configurable extended-check - provide option to enable/disable lag check - default to lag-aware check with AVAILABILITY_LAG_TOLERANCE_DEFAULT of 100ms * - fix java doc issue * - formatting * -fix doc issue * - formatting * revert introduce healtCheckMetaConfig - introduces type unsafe warnings, revert till they are resovled * Add list constructor * Add option for rate limiter to MultiThreadedFakeApp * Use /v1/local/bdbs/<int:uid>/endpoint/availability - use /v1/local/bdbs/<int:uid>/endpoint/availability instead of availability address vs /v1/bdbs/<int:uid>/availability * Add builder factory method for base HealthCheckStrategy.Config * format * format * revert to /v1/bdbs/<int:uid>/availability reading again the spec /local is inteded to be used when configuring LoadBalancers * revert to /v1/bdbs/<int:uid>/availability reading again the spec /local is inteded to be used when configuring LoadBalancers * format * fix unit test after revert of local * format * Address review comments - remove misleading default value comment - renamed Config.endpoint to Config.restEndpoint - renamed dataPathAvailability -> databaseAvailability --------- Co-authored-by: ggivo <[email protected]>
1 parent e2b73ce commit c46a492

15 files changed

+1526
-330
lines changed

pom.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,8 +341,11 @@
341341
<include>src/main/java/redis/clients/jedis/mcf/*.java</include>
342342
<include>src/test/java/redis/clients/jedis/failover/*.java</include>
343343
<include>src/test/java/redis/clients/jedis/mcf/EchoStrategyIntegrationTest.java</include>
344+
<include>src/test/java/redis/clients/jedis/mcf/LagAwareStrategyUnitTest.java</include>
345+
<include>src/test/java/redis/clients/jedis/mcf/RedisRestAPI*.java</include>
344346
<include>src/test/java/redis/clients/jedis/mcf/HealthCheckTest.java</include>
345347
<include>src/test/java/redis/clients/jedis/misc/AutomaticFailoverTest.java</include>
348+
<include>src/test/java/redis/clients/jedis/scenario/ActiveActiveFailoverTest.java</include>
346349
<include>src/main/java/redis/clients/jedis/providers/MultiClusterPooledConnectionProvider.java</include>
347350
<include>src/main/java/redis/clients/jedis/MultiClusterClientConfig.java</include>
348351
<include>src/main/java/redis/clients/jedis/HostAndPort.java</include>

src/main/java/redis/clients/jedis/MultiClusterClientConfig.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -259,30 +259,34 @@ public static Builder builder(ClusterConfig[] clusterConfigs) {
259259
return new Builder(clusterConfigs);
260260
}
261261

262+
public static Builder builder(List<ClusterConfig> clusterConfigs) {
263+
return new Builder(clusterConfigs);
264+
}
265+
262266
public static class ClusterConfig {
263267

264268
private HostAndPort hostAndPort;
265-
private JedisClientConfig clientConfig;
269+
private JedisClientConfig jedisClientConfig;
266270
private GenericObjectPoolConfig<Connection> connectionPoolConfig;
267271

268272
private float weight = 1.0f;
269273
private StrategySupplier healthCheckStrategySupplier;
270274

271275
public ClusterConfig(HostAndPort hostAndPort, JedisClientConfig clientConfig) {
272276
this.hostAndPort = hostAndPort;
273-
this.clientConfig = clientConfig;
277+
this.jedisClientConfig = clientConfig;
274278
}
275279

276280
public ClusterConfig(HostAndPort hostAndPort, JedisClientConfig clientConfig,
277281
GenericObjectPoolConfig<Connection> connectionPoolConfig) {
278282
this.hostAndPort = hostAndPort;
279-
this.clientConfig = clientConfig;
283+
this.jedisClientConfig = clientConfig;
280284
this.connectionPoolConfig = connectionPoolConfig;
281285
}
282286

283287
private ClusterConfig(Builder builder) {
284288
this.hostAndPort = builder.hostAndPort;
285-
this.clientConfig = builder.clientConfig;
289+
this.jedisClientConfig = builder.jedisClientConfig;
286290
this.connectionPoolConfig = builder.connectionPoolConfig;
287291
this.weight = builder.weight;
288292
this.healthCheckStrategySupplier = builder.healthCheckStrategySupplier;
@@ -297,7 +301,7 @@ public static Builder builder(HostAndPort hostAndPort, JedisClientConfig clientC
297301
}
298302

299303
public JedisClientConfig getJedisClientConfig() {
300-
return clientConfig;
304+
return jedisClientConfig;
301305
}
302306

303307
public GenericObjectPoolConfig<Connection> getConnectionPoolConfig() {
@@ -314,15 +318,15 @@ public StrategySupplier getHealthCheckStrategySupplier() {
314318

315319
public static class Builder {
316320
private HostAndPort hostAndPort;
317-
private JedisClientConfig clientConfig;
321+
private JedisClientConfig jedisClientConfig;
318322
private GenericObjectPoolConfig<Connection> connectionPoolConfig;
319323

320324
private float weight = 1.0f;
321325
private StrategySupplier healthCheckStrategySupplier = EchoStrategy.DEFAULT;
322326

323327
public Builder(HostAndPort hostAndPort, JedisClientConfig clientConfig) {
324328
this.hostAndPort = hostAndPort;
325-
this.clientConfig = clientConfig;
329+
this.jedisClientConfig = clientConfig;
326330
}
327331

328332
public Builder connectionPoolConfig(GenericObjectPoolConfig<Connection> connectionPoolConfig) {

src/main/java/redis/clients/jedis/mcf/EchoStrategy.java

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,36 +10,32 @@
1010
public class EchoStrategy implements HealthCheckStrategy {
1111
private static final Logger log = LoggerFactory.getLogger(EchoStrategy.class);
1212

13-
private int interval;
14-
private int timeout;
15-
private UnifiedJedis jedis;
16-
private int minConsecutiveSuccessCount;
13+
private final UnifiedJedis jedis;
14+
private final HealthCheckStrategy.Config config;
1715

1816
public EchoStrategy(HostAndPort hostAndPort, JedisClientConfig jedisClientConfig) {
19-
this(hostAndPort, jedisClientConfig, 1000, 1000, 3);
17+
this(hostAndPort, jedisClientConfig, new HealthCheckStrategy.Config(1000, 1000, 3));
2018
}
2119

22-
public EchoStrategy(HostAndPort hostAndPort, JedisClientConfig jedisClientConfig, int interval, int timeout,
23-
int minConsecutiveSuccessCount) {
24-
this.interval = interval;
25-
this.timeout = timeout;
26-
this.minConsecutiveSuccessCount = minConsecutiveSuccessCount;
20+
public EchoStrategy(HostAndPort hostAndPort, JedisClientConfig jedisClientConfig,
21+
HealthCheckStrategy.Config config) {
2722
this.jedis = new UnifiedJedis(hostAndPort, jedisClientConfig);
23+
this.config = config;
2824
}
2925

3026
@Override
3127
public int getInterval() {
32-
return interval;
28+
return config.getInterval();
3329
}
3430

3531
@Override
3632
public int getTimeout() {
37-
return timeout;
33+
return config.getTimeout();
3834
}
3935

4036
@Override
4137
public int minConsecutiveSuccessCount() {
42-
return minConsecutiveSuccessCount;
38+
return config.getMinConsecutiveSuccessCount();
4339
}
4440

4541
@Override
@@ -57,8 +53,6 @@ public void close() {
5753
jedis.close();
5854
}
5955

60-
public static final StrategySupplier DEFAULT = (hostAndPort, jedisClientConfig) -> {
61-
return new EchoStrategy(hostAndPort, jedisClientConfig);
62-
};
56+
public static final StrategySupplier DEFAULT = EchoStrategy::new;
6357

6458
}

src/main/java/redis/clients/jedis/mcf/HealthCheckStrategy.java

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,95 @@ default int getMaxWaitDuration() {
4646
return ((minConsecutiveSuccessCount() + 1) * (getInterval() + getTimeout()));
4747
}
4848

49+
public static class Config {
50+
protected final int interval;
51+
protected final int timeout;
52+
protected final int minConsecutiveSuccessCount;
53+
54+
public Config(int interval, int timeout, int minConsecutiveSuccessCount) {
55+
this.interval = interval;
56+
this.timeout = timeout;
57+
this.minConsecutiveSuccessCount = minConsecutiveSuccessCount;
58+
}
59+
60+
public int getInterval() {
61+
return interval;
62+
}
63+
64+
public int getTimeout() {
65+
return timeout;
66+
}
67+
68+
public int getMinConsecutiveSuccessCount() {
69+
return minConsecutiveSuccessCount;
70+
}
71+
72+
/**
73+
* Create a new Config instance with default values.
74+
* @return a new Config instance
75+
*/
76+
public static Config create() {
77+
return new Builder<>().build();
78+
}
79+
80+
/**
81+
* Create a new builder for HealthCheckStrategy.Config.
82+
* @return a new Builder instance
83+
*/
84+
public static Builder<?, Config> builder() {
85+
return new Builder<>();
86+
}
87+
88+
/**
89+
* Base builder for HealthCheckStrategy.Config and its subclasses.
90+
* @param <T> the builder type (for fluent API)
91+
* @param <C> the config type being built
92+
*/
93+
public static class Builder<T extends Builder<T, C>, C extends Config> {
94+
protected int interval = 1000;
95+
protected int timeout = 1000;
96+
protected int minConsecutiveSuccessCount = 3;
97+
98+
/**
99+
* Set the interval between health checks in milliseconds.
100+
* @param interval the interval in milliseconds (default: 1000)
101+
* @return this builder
102+
*/
103+
@SuppressWarnings("unchecked")
104+
public T interval(int interval) {
105+
this.interval = interval;
106+
return (T) this;
107+
}
108+
109+
/**
110+
* Set the timeout for health checks in milliseconds.
111+
* @param timeout the timeout in milliseconds (default: 1000)
112+
* @return this builder
113+
*/
114+
@SuppressWarnings("unchecked")
115+
public T timeout(int timeout) {
116+
this.timeout = timeout;
117+
return (T) this;
118+
}
119+
120+
/**
121+
* Set the minimum number of consecutive successful health checks required.
122+
* @param minConsecutiveSuccessCount the minimum count (default: 3)
123+
* @return this builder
124+
*/
125+
@SuppressWarnings("unchecked")
126+
public T minConsecutiveSuccessCount(int minConsecutiveSuccessCount) {
127+
this.minConsecutiveSuccessCount = minConsecutiveSuccessCount;
128+
return (T) this;
129+
}
130+
131+
/**
132+
* Build the Config instance.
133+
* @return a new Config instance
134+
*/
135+
public Config build() {
136+
return new Config(interval, timeout, minConsecutiveSuccessCount);
137+
}
138+
}
139+
}
49140
}

0 commit comments

Comments
 (0)