From 1b65cf3fe567b5b3bd76850723c4d3ca0b6b6dd1 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Sun, 31 Dec 2023 11:45:29 +0600 Subject: [PATCH] Added doc and renamed --- docs/failover.md | 16 +++++++++--- .../jedis/MultiClusterClientConfig.java | 25 ++++++++++--------- .../mcf/CircuitBreakerCommandExecutor.java | 4 +-- ...cuitBreakerFailoverConnectionProvider.java | 4 +-- .../MultiClusterPooledConnectionProvider.java | 19 ++++++++------ .../jedis/misc/AutomaticFailoverTest.java | 2 +- 6 files changed, 41 insertions(+), 29 deletions(-) diff --git a/docs/failover.md b/docs/failover.md index 8414e41376..38fdc8c97b 100644 --- a/docs/failover.md +++ b/docs/failover.md @@ -99,8 +99,8 @@ Jedis uses the following retry settings: | Max retry attempts | 3 | Maximum number of retry attempts (including the initial call) | | Retry wait duration | 500 ms | Number of milliseconds to wait between retry attempts | | Wait duration backoff multiplier | 2 | Exponential backoff factor multiplied against wait duration between retries. For example, with a wait duration of 1 second and a multiplier of 2, the retries would occur after 1s, 2s, 4s, 8s, 16s, and so on. | -| Retry included exception list | `JedisConnectionException` | A list of `Throwable` classes that count as failures and should be retried. | -| Retry ignored exception list | Empty list | A list of `Throwable` classes to explicitly ignore for the purposes of retry. | +| Retry included exception list | [JedisConnectionException] | A list of Throwable classes that count as failures and should be retried. | +| Retry ignored exception list | null | A list of Throwable classes to explicitly ignore for the purposes of retry. | To disable retry, set `maxRetryAttempts` to 1. @@ -116,8 +116,16 @@ Jedis uses the following circuit breaker settings: | Failure rate threshold | `50.0f` | Percentage of calls within the sliding window that must fail before the circuit breaker transitions to the `OPEN` state. | | Slow call duration threshold | 60000 ms | Duration threshold above which calls are classified as slow and added to the sliding window. | | Slow call rate threshold | `100.0f` | Percentage of calls within the sliding window that exceed the slow call duration threshold before circuit breaker transitions to the `OPEN` state. | -| Circuit breaker included exception list | `JedisConnectionException` | A list of `Throwable` classes that count as failures and add to the failure rate. | -| Circuit breaker ignored exception list | Empty list | A list of `Throwable` classes to explicitly ignore for failure rate calculations. | | +| Circuit breaker included exception list | [JedisConnectionException] | A list of Throwable classes that count as failures and add to the failure rate. | +| Circuit breaker ignored exception list | null | A list of Throwable classes to explicitly ignore for failure rate calculations. | | + +### Fallback configuration + +Jedis uses the following fallback settings: + +| Setting | Default value | Description | +|-------------------------|-------------------------------------------------------|----------------------------------------------------| +| Fallback exception list | [CallNotPermittedException, JedisConnectionException] | A list of Throwable classes that trigger fallback. | ### Failover callbacks diff --git a/src/main/java/redis/clients/jedis/MultiClusterClientConfig.java b/src/main/java/redis/clients/jedis/MultiClusterClientConfig.java index bc57c5fd63..e661d5c2b3 100644 --- a/src/main/java/redis/clients/jedis/MultiClusterClientConfig.java +++ b/src/main/java/redis/clients/jedis/MultiClusterClientConfig.java @@ -2,13 +2,14 @@ import io.github.resilience4j.circuitbreaker.CallNotPermittedException; import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig.SlidingWindowType; -import redis.clients.jedis.exceptions.JedisConnectionException; -import redis.clients.jedis.exceptions.JedisValidationException; import java.time.Duration; import java.util.Arrays; import java.util.List; +import redis.clients.jedis.exceptions.JedisConnectionException; +import redis.clients.jedis.exceptions.JedisValidationException; + /** * @author Allen Terleto (aterleto) @@ -39,7 +40,7 @@ public final class MultiClusterClientConfig { private static final float CIRCUIT_BREAKER_SLOW_CALL_RATE_THRESHOLD_DEFAULT = 100.0f; // measured as percentage private static final List CIRCUIT_BREAKER_INCLUDED_EXCEPTIONS_DEFAULT = Arrays.asList(JedisConnectionException.class); - private static final List> CIRCUIT_BREAKER_FALLBACK_EXCEPTIONS_DEFAULT = + private static final List> FALLBACK_EXCEPTIONS_DEFAULT = Arrays.asList(CallNotPermittedException.class, JedisConnectionException.class); private final ClusterConfig[] clusterConfigs; @@ -104,7 +105,7 @@ public final class MultiClusterClientConfig { * failure nor success, even if the exceptions is part of recordExceptions */ private List circuitBreakerIgnoreExceptionList; - private List> circuitBreakerFallbackExceptionList; + private List> fallbackExceptionList; public MultiClusterClientConfig(ClusterConfig[] clusterConfigs) { this.clusterConfigs = clusterConfigs; @@ -166,8 +167,8 @@ public SlidingWindowType getCircuitBreakerSlidingWindowType() { return circuitBreakerSlidingWindowType; } - public List> getCircuitBreakerFallbackExceptionList() { - return circuitBreakerFallbackExceptionList; + public List> getFallbackExceptionList() { + return fallbackExceptionList; } public static class ClusterConfig { @@ -216,7 +217,7 @@ public static class Builder { private float circuitBreakerSlowCallRateThreshold = CIRCUIT_BREAKER_SLOW_CALL_RATE_THRESHOLD_DEFAULT; private List circuitBreakerIncludedExceptionList = CIRCUIT_BREAKER_INCLUDED_EXCEPTIONS_DEFAULT; private List circuitBreakerIgnoreExceptionList = null; - private List> circuitBreakerFallbackExceptionList = CIRCUIT_BREAKER_FALLBACK_EXCEPTIONS_DEFAULT; + private List> fallbackExceptionList = FALLBACK_EXCEPTIONS_DEFAULT; public Builder(ClusterConfig[] clusterConfigs) { @@ -298,8 +299,8 @@ public Builder circuitBreakerIgnoreExceptionList(List circuitBreakerIgnor return this; } - public Builder circuitBreakerFallbackExceptionList(List> circuitBreakerFallbackExceptionList) { - this.circuitBreakerFallbackExceptionList = circuitBreakerFallbackExceptionList; + public Builder fallbackExceptionList(List> fallbackExceptionList) { + this.fallbackExceptionList = fallbackExceptionList; return this; } @@ -337,10 +338,10 @@ public MultiClusterClientConfig build() { config.circuitBreakerIgnoreExceptionList = this.circuitBreakerIgnoreExceptionList; } - if (this.circuitBreakerFallbackExceptionList != null && !this.circuitBreakerFallbackExceptionList.isEmpty()) { - config.circuitBreakerFallbackExceptionList = this.circuitBreakerFallbackExceptionList; + if (this.fallbackExceptionList != null && !this.fallbackExceptionList.isEmpty()) { + config.fallbackExceptionList = this.fallbackExceptionList; } else { - config.circuitBreakerFallbackExceptionList = CIRCUIT_BREAKER_FALLBACK_EXCEPTIONS_DEFAULT; + config.fallbackExceptionList = FALLBACK_EXCEPTIONS_DEFAULT; } return config; diff --git a/src/main/java/redis/clients/jedis/mcf/CircuitBreakerCommandExecutor.java b/src/main/java/redis/clients/jedis/mcf/CircuitBreakerCommandExecutor.java index 2f4d472286..38b32bbad0 100644 --- a/src/main/java/redis/clients/jedis/mcf/CircuitBreakerCommandExecutor.java +++ b/src/main/java/redis/clients/jedis/mcf/CircuitBreakerCommandExecutor.java @@ -32,8 +32,8 @@ public T executeCommand(CommandObject commandObject) { supplier.withRetry(cluster.getRetry()); supplier.withCircuitBreaker(cluster.getCircuitBreaker()); - supplier.withFallback(provider.getCircuitBreakerFallbackExceptionList(), - e -> this.handleClusterFailover(commandObject, cluster.getCircuitBreaker())); + supplier.withFallback(provider.getFallbackExceptionList(), + e -> this.handleClusterFailover(commandObject, cluster.getCircuitBreaker())); return supplier.decorate().get(); } diff --git a/src/main/java/redis/clients/jedis/mcf/CircuitBreakerFailoverConnectionProvider.java b/src/main/java/redis/clients/jedis/mcf/CircuitBreakerFailoverConnectionProvider.java index 03c9bcbd49..10a0823973 100644 --- a/src/main/java/redis/clients/jedis/mcf/CircuitBreakerFailoverConnectionProvider.java +++ b/src/main/java/redis/clients/jedis/mcf/CircuitBreakerFailoverConnectionProvider.java @@ -26,8 +26,8 @@ public Connection getConnection() { supplier.withRetry(cluster.getRetry()); supplier.withCircuitBreaker(cluster.getCircuitBreaker()); - supplier.withFallback(provider.getCircuitBreakerFallbackExceptionList(), - e -> this.handleClusterFailover(cluster.getCircuitBreaker())); + supplier.withFallback(provider.getFallbackExceptionList(), + e -> this.handleClusterFailover(cluster.getCircuitBreaker())); return supplier.decorate().get(); } diff --git a/src/main/java/redis/clients/jedis/providers/MultiClusterPooledConnectionProvider.java b/src/main/java/redis/clients/jedis/providers/MultiClusterPooledConnectionProvider.java index e1b6196fb0..e6013a2c58 100644 --- a/src/main/java/redis/clients/jedis/providers/MultiClusterPooledConnectionProvider.java +++ b/src/main/java/redis/clients/jedis/providers/MultiClusterPooledConnectionProvider.java @@ -8,18 +8,21 @@ import io.github.resilience4j.retry.Retry; import io.github.resilience4j.retry.RetryConfig; import io.github.resilience4j.retry.RetryRegistry; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Consumer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import redis.clients.jedis.*; import redis.clients.jedis.MultiClusterClientConfig.ClusterConfig; import redis.clients.jedis.exceptions.JedisConnectionException; import redis.clients.jedis.exceptions.JedisValidationException; import redis.clients.jedis.util.Pool; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Consumer; - /** * @author Allen Terleto (aterleto) @@ -63,7 +66,7 @@ public class MultiClusterPooledConnectionProvider implements ConnectionProvider */ private Consumer clusterFailoverPostProcessor; - private List> circuitBreakerFallbackExceptionList; + private List> fallbackExceptionList; public MultiClusterPooledConnectionProvider(MultiClusterClientConfig multiClusterClientConfig) { @@ -132,7 +135,7 @@ public MultiClusterPooledConnectionProvider(MultiClusterClientConfig multiCluste /// --- /// - this.circuitBreakerFallbackExceptionList = multiClusterClientConfig.getCircuitBreakerFallbackExceptionList(); + this.fallbackExceptionList = multiClusterClientConfig.getFallbackExceptionList(); } /** @@ -295,8 +298,8 @@ public void setClusterFailoverPostProcessor(Consumer clusterFailoverPost this.clusterFailoverPostProcessor = clusterFailoverPostProcessor; } - public List> getCircuitBreakerFallbackExceptionList() { - return circuitBreakerFallbackExceptionList; + public List> getFallbackExceptionList() { + return fallbackExceptionList; } public static class Cluster { diff --git a/src/test/java/redis/clients/jedis/misc/AutomaticFailoverTest.java b/src/test/java/redis/clients/jedis/misc/AutomaticFailoverTest.java index 54988c71c4..dc03c52f39 100644 --- a/src/test/java/redis/clients/jedis/misc/AutomaticFailoverTest.java +++ b/src/test/java/redis/clients/jedis/misc/AutomaticFailoverTest.java @@ -160,7 +160,7 @@ public void failoverFromAuthError() { getClusterConfigs(clientConfig, hostPort_1_2, hostPort_2)) .circuitBreakerSlidingWindowMinCalls(slidingWindowMinCalls) .circuitBreakerSlidingWindowSize(slidingWindowSize) - .circuitBreakerFallbackExceptionList(Arrays.asList(JedisAccessControlException.class)); + .fallbackExceptionList(Arrays.asList(JedisAccessControlException.class)); RedisFailoverReporter failoverReporter = new RedisFailoverReporter(); MultiClusterPooledConnectionProvider cacheProvider = new MultiClusterPooledConnectionProvider(builder.build());