Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ CRDB
Dockerfile
EVAL
EVALSHA
EchoStrategy
FTCreateParams
FTSearchParams
Failback
Expand Down Expand Up @@ -71,6 +70,7 @@ OpenCensus
OpenTelemetry
OpenTracing
Otel
PingStrategy
POJO
POJOs
PoolConfig
Expand Down
8 changes: 4 additions & 4 deletions docs/failover.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,18 +159,18 @@ The health check system operates independently of your application traffic, runn

#### Available Health Check Types

##### 1. EchoStrategy (Default)
##### 1. PingStrategy (Default)

The `EchoStrategy` is the default health check implementation that uses Redis's `ECHO` command to verify both connectivity and write capability.
The `PingStrategy` is the default health check implementation that uses Redis's `PING` command to verify both connectivity and write capability.

**Use Cases:**
- General-purpose health checking for most Redis deployments
- Verifying both read and write operations
- Simple connectivity validation

**How it works:**
- Sends `ECHO "HealthCheck"` command to the Redis server
- Expects exact response `"HealthCheck"` to consider the server healthy
- Sends `PING` command to the Redis server
- Expects exact response `"PONG"` to consider the server healthy
- Any exception or unexpected response marks the server as unhealthy

##### 2. LagAwareStrategy [PREVIEW] (Redis Enterprise)
Expand Down
24 changes: 12 additions & 12 deletions src/main/java/redis/clients/jedis/MultiDbConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import redis.clients.jedis.exceptions.JedisConnectionException;
import redis.clients.jedis.exceptions.JedisValidationException;
import redis.clients.jedis.mcf.ConnectionFailoverException;
import redis.clients.jedis.mcf.EchoStrategy;
import redis.clients.jedis.mcf.PingStrategy;
import redis.clients.jedis.mcf.HealthCheckStrategy;

/**
Expand Down Expand Up @@ -71,7 +71,7 @@
* </p>
* @see redis.clients.jedis.mcf.MultiDbConnectionProvider
* @see redis.clients.jedis.mcf.HealthCheckStrategy
* @see redis.clients.jedis.mcf.EchoStrategy
* @see redis.clients.jedis.mcf.PingStrategy
* @see redis.clients.jedis.mcf.LagAwareStrategy
* @since 7.0
*/
Expand All @@ -90,13 +90,13 @@ public final class MultiDbConfig {
* <strong>Common Implementations:</strong>
* </p>
* <ul>
* <li>{@link redis.clients.jedis.mcf.EchoStrategy#DEFAULT} - Uses Redis ECHO command for health
* <li>{@link redis.clients.jedis.mcf.PingStrategy#DEFAULT} - Uses Redis PING command for health
* checks</li>
* <li>Custom implementations for specific monitoring requirements</li>
* <li>Redis Enterprise implementations using REST API monitoring</li>
* </ul>
* @see redis.clients.jedis.mcf.HealthCheckStrategy
* @see redis.clients.jedis.mcf.EchoStrategy
* @see redis.clients.jedis.mcf.PingStrategy
* @see redis.clients.jedis.mcf.LagAwareStrategy
*/
public static interface StrategySupplier {
Expand Down Expand Up @@ -839,15 +839,15 @@ public static class DatabaseConfig {

/**
* Strategy supplier for creating health check instances for this database. Default is
* EchoStrategy.DEFAULT.
* PingStrategy.DEFAULT.
*/
private StrategySupplier healthCheckStrategySupplier;

/**
* Constructs a DatabaseConfig with basic endpoint and client configuration.
* <p>
* This constructor creates a database configuration with default settings: weight of 1.0f and
* EchoStrategy for health checks. Use the {@link Builder} for more advanced configuration
* PingStrategy for health checks. Use the {@link Builder} for more advanced configuration
* options.
* </p>
* @param endpoint the Redis endpoint (host and port)
Expand All @@ -863,7 +863,7 @@ public DatabaseConfig(Endpoint endpoint, JedisClientConfig clientConfig) {
* Constructs a DatabaseConfig with endpoint, client, and connection pool configuration.
* <p>
* This constructor allows specification of connection pool settings in addition to basic
* endpoint configuration. Default weight of 1.0f and EchoStrategy for health checks are used.
* endpoint configuration. Default weight of 1.0f and PingStrategy for health checks are used.
* </p>
* @param endpoint the Redis endpoint (host and port)
* @param clientConfig the Jedis client configuration
Expand Down Expand Up @@ -963,7 +963,7 @@ public StrategySupplier getHealthCheckStrategySupplier() {
* </p>
* <ul>
* <li><strong>Weight:</strong> 1.0f (standard priority)</li>
* <li><strong>Health Check:</strong> {@link redis.clients.jedis.mcf.EchoStrategy#DEFAULT}</li>
* <li><strong>Health Check:</strong> {@link redis.clients.jedis.mcf.PingStrategy#DEFAULT}</li>
* <li><strong>Connection Pool:</strong> null (uses default pooling)</li>
* </ul>
*/
Expand All @@ -980,8 +980,8 @@ public static class Builder {
/** Weight for database selection priority. Default: 1.0f */
private float weight = 1.0f;

/** Health check strategy supplier. Default: EchoStrategy.DEFAULT */
private StrategySupplier healthCheckStrategySupplier = EchoStrategy.DEFAULT;
/** Health check strategy supplier. Default: PingStrategy.DEFAULT */
private StrategySupplier healthCheckStrategySupplier = PingStrategy.DEFAULT;

/**
* Constructs a new Builder with required endpoint and client configuration.
Expand Down Expand Up @@ -1089,7 +1089,7 @@ public Builder healthCheckStrategy(HealthCheckStrategy healthCheckStrategy) {
* </ul>
* <p>
* When health checks are enabled (true) and no strategy supplier was previously set, the
* default {@link redis.clients.jedis.mcf.EchoStrategy#DEFAULT} will be used.
* default {@link redis.clients.jedis.mcf.PingStrategy#DEFAULT} will be used.
* </p>
* @param healthCheckEnabled true to enable health checks, false to disable
* @return this builder instance for method chaining
Expand All @@ -1098,7 +1098,7 @@ public Builder healthCheckEnabled(boolean healthCheckEnabled) {
if (!healthCheckEnabled) {
this.healthCheckStrategySupplier = null;
} else if (healthCheckStrategySupplier == null) {
this.healthCheckStrategySupplier = EchoStrategy.DEFAULT;
this.healthCheckStrategySupplier = PingStrategy.DEFAULT;
}
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@
import redis.clients.jedis.UnifiedJedis;
import redis.clients.jedis.MultiDbConfig.StrategySupplier;

public class EchoStrategy implements HealthCheckStrategy {
public class PingStrategy implements HealthCheckStrategy {
private static final int MAX_HEALTH_CHECK_POOL_SIZE = 2;

private final UnifiedJedis jedis;
private final HealthCheckStrategy.Config config;

public EchoStrategy(HostAndPort hostAndPort, JedisClientConfig jedisClientConfig) {
public PingStrategy(HostAndPort hostAndPort, JedisClientConfig jedisClientConfig) {
this(hostAndPort, jedisClientConfig, HealthCheckStrategy.Config.create());
}

public EchoStrategy(HostAndPort hostAndPort, JedisClientConfig jedisClientConfig,
public PingStrategy(HostAndPort hostAndPort, JedisClientConfig jedisClientConfig,
HealthCheckStrategy.Config config) {
GenericObjectPoolConfig<Connection> poolConfig = new GenericObjectPoolConfig<>();
poolConfig.setMaxTotal(MAX_HEALTH_CHECK_POOL_SIZE);
Expand Down Expand Up @@ -55,15 +55,14 @@ public int getDelayInBetweenProbes() {

@Override
public HealthStatus doHealthCheck(Endpoint endpoint) {
return "HealthCheck".equals(jedis.echo("HealthCheck")) ? HealthStatus.HEALTHY
: HealthStatus.UNHEALTHY;
return "PONG".equals(jedis.ping()) ? HealthStatus.HEALTHY : HealthStatus.UNHEALTHY;
}

@Override
public void close() {
jedis.close();
}

public static final StrategySupplier DEFAULT = EchoStrategy::new;
public static final StrategySupplier DEFAULT = PingStrategy::new;

}
4 changes: 2 additions & 2 deletions src/test/java/redis/clients/jedis/mcf/DefaultValuesTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ void testDefaultValuesInConfig() {
// check healthchecks enabled
assertNotNull(databaseConfig.getHealthCheckStrategySupplier());

// check default healthcheck strategy is echo
assertEquals(EchoStrategy.DEFAULT, databaseConfig.getHealthCheckStrategySupplier());
// check default healthcheck strategy is PingStrategy
assertEquals(PingStrategy.DEFAULT, databaseConfig.getHealthCheckStrategySupplier());

// check number of probes
assertEquals(3,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ public void testDisableHealthCheck() {

@Test
public void testDefaultStrategySupplier() {
// Create a default strategy supplier that creates EchoStrategy instances
// Create a default strategy supplier that creates PingStrategy instances
MultiDbConfig.StrategySupplier defaultSupplier = (hostAndPort, jedisClientConfig) -> {
return new EchoStrategy(hostAndPort, jedisClientConfig);
return new PingStrategy(hostAndPort, jedisClientConfig);
};
MultiDbConnectionProvider customProvider = getMCCF(defaultSupplier);
try (UnifiedJedis customClient = new UnifiedJedis(customProvider)) {
Expand Down Expand Up @@ -113,8 +113,8 @@ public void testProbingLogic_RealHealthCheckWithProbes() throws InterruptedExcep
}
// Third attempt succeeds - do actual health check
try (UnifiedJedis jedis = new UnifiedJedis(hostAndPort, jedisClientConfig)) {
String result = jedis.echo("HealthCheck");
return "HealthCheck".equals(result) ? HealthStatus.HEALTHY : HealthStatus.UNHEALTHY;
String result = jedis.ping();
return "PONG".equals(result) ? HealthStatus.HEALTHY : HealthStatus.UNHEALTHY;
} catch (Exception e) {
return HealthStatus.UNHEALTHY;
}
Expand Down
34 changes: 17 additions & 17 deletions src/test/java/redis/clients/jedis/mcf/HealthCheckTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -321,11 +321,11 @@ void testHealthStatusManagerClose() {
verify(closeableStrategy).close();
}

// ========== EchoStrategy Tests ==========
// ========== PingStrategy Tests ==========

@Test
void testEchoStrategyCustomIntervalTimeout() {
try (EchoStrategy strategy = new EchoStrategy(testEndpoint, testConfig,
void testPingStrategyCustomIntervalTimeout() {
try (PingStrategy strategy = new PingStrategy(testEndpoint, testConfig,
HealthCheckStrategy.Config.builder().interval(2000).timeout(1500).delayInBetweenProbes(50)
.numProbes(11).policy(BuiltIn.ANY_SUCCESS).build())) {
assertEquals(2000, strategy.getInterval());
Expand All @@ -337,11 +337,11 @@ void testEchoStrategyCustomIntervalTimeout() {
}

@Test
void testEchoStrategyDefaultSupplier() {
MultiDbConfig.StrategySupplier supplier = EchoStrategy.DEFAULT;
void testPingStrategyDefaultSupplier() {
MultiDbConfig.StrategySupplier supplier = PingStrategy.DEFAULT;
HealthCheckStrategy strategy = supplier.get(testEndpoint, testConfig);

assertInstanceOf(EchoStrategy.class, strategy);
assertInstanceOf(PingStrategy.class, strategy);
}

// ========== Failover configuration Tests ==========
Expand All @@ -368,7 +368,7 @@ void testDefaultValues() {
.builder(testEndpoint, testConfig).build();

assertEquals(1.0f, databaseConfig.getWeight()); // Default weight
assertEquals(EchoStrategy.DEFAULT, databaseConfig.getHealthCheckStrategySupplier()); // Default
assertEquals(PingStrategy.DEFAULT, databaseConfig.getHealthCheckStrategySupplier()); // Default
// is null
// (no
// health
Expand Down Expand Up @@ -410,26 +410,26 @@ void testDatabaseConfigWithStrategySupplier() {
}

@Test
void testDatabaseConfigWithEchoStrategy() {
MultiDbConfig.StrategySupplier echoSupplier = (hostAndPort, jedisClientConfig) -> {
return new EchoStrategy(hostAndPort, jedisClientConfig);
void testDatabaseConfigWithPingStrategy() {
MultiDbConfig.StrategySupplier pingSupplier = (hostAndPort, jedisClientConfig) -> {
return new PingStrategy(hostAndPort, jedisClientConfig);
};

MultiDbConfig.DatabaseConfig databaseConfig = MultiDbConfig.DatabaseConfig
.builder(testEndpoint, testConfig).healthCheckStrategySupplier(echoSupplier).build();
.builder(testEndpoint, testConfig).healthCheckStrategySupplier(pingSupplier).build();

MultiDbConfig.StrategySupplier supplier = databaseConfig.getHealthCheckStrategySupplier();
assertNotNull(supplier);
assertInstanceOf(EchoStrategy.class, supplier.get(testEndpoint, testConfig));
assertInstanceOf(PingStrategy.class, supplier.get(testEndpoint, testConfig));
}

@Test
void testDatabaseConfigWithDefaultHealthCheck() {
MultiDbConfig.DatabaseConfig databaseConfig = MultiDbConfig.DatabaseConfig
.builder(testEndpoint, testConfig).build(); // Should use default EchoStrategy
.builder(testEndpoint, testConfig).build(); // Should use default PingStrategy

assertNotNull(databaseConfig.getHealthCheckStrategySupplier());
assertEquals(EchoStrategy.DEFAULT, databaseConfig.getHealthCheckStrategySupplier());
assertEquals(PingStrategy.DEFAULT, databaseConfig.getHealthCheckStrategySupplier());
}

@Test
Expand All @@ -446,7 +446,7 @@ void testDatabaseConfigHealthCheckEnabledExplicitly() {
.builder(testEndpoint, testConfig).healthCheckEnabled(true).build();

assertNotNull(databaseConfig.getHealthCheckStrategySupplier());
assertEquals(EchoStrategy.DEFAULT, databaseConfig.getHealthCheckStrategySupplier());
assertEquals(PingStrategy.DEFAULT, databaseConfig.getHealthCheckStrategySupplier());
}

// ========== Integration Tests ==========
Expand Down Expand Up @@ -516,10 +516,10 @@ void testStrategySupplierPolymorphism() {
// Test that the polymorphic design works correctly
MultiDbConfig.StrategySupplier supplier = (hostAndPort, jedisClientConfig) -> {
if (jedisClientConfig != null) {
return new EchoStrategy(hostAndPort, jedisClientConfig,
return new PingStrategy(hostAndPort, jedisClientConfig,
HealthCheckStrategy.Config.builder().interval(500).timeout(250).numProbes(1).build());
} else {
return new EchoStrategy(hostAndPort, DefaultJedisClientConfig.builder().build());
return new PingStrategy(hostAndPort, DefaultJedisClientConfig.builder().build());
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ void testInitializationWithMixedHealthCheckConfiguration() {
.build();

DatabaseConfig db2 = DatabaseConfig.builder(endpoint2, clientConfig).weight(2.0f)
.healthCheckStrategySupplier(EchoStrategy.DEFAULT) // With
.healthCheckStrategySupplier(PingStrategy.DEFAULT) // With
// health
// check
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import static org.junit.jupiter.api.Assertions.*;

@Tag("failover")
public class EchoStrategyIntegrationTest {
public class PingStrategyIntegrationTest {

private static final EndpointConfig endpoint = HostAndPorts.getRedisEndpoint("redis-failover-1");
private static final HostAndPort proxyHostAndPort = endpoint.getHostAndPort();
Expand Down Expand Up @@ -55,10 +55,10 @@ public void resetProxy() throws IOException {
}

@Test
public void testEchoStrategyRecoversAfterDisconnect() throws Exception {
public void testPingStrategyRecoversAfterDisconnect() throws Exception {
JedisClientConfig config = DefaultJedisClientConfig.builder().socketTimeoutMillis(1000)
.connectionTimeoutMillis(1000).build();
try (EchoStrategy strategy = new EchoStrategy(proxyHostAndPort, config,
try (PingStrategy strategy = new PingStrategy(proxyHostAndPort, config,
HealthCheckStrategy.Config.create())) {

// Initial health check should work
Expand All @@ -81,11 +81,11 @@ public void testEchoStrategyRecoversAfterDisconnect() throws Exception {
}

@Test
public void testEchoStrategyWithConnectionTimeout() throws Exception {
public void testPingStrategyWithConnectionTimeout() throws Exception {
JedisClientConfig config = DefaultJedisClientConfig.builder().socketTimeoutMillis(100)
.connectionTimeoutMillis(100).build();

try (EchoStrategy strategy = new EchoStrategy(proxyHostAndPort, config,
try (PingStrategy strategy = new PingStrategy(proxyHostAndPort, config,
HealthCheckStrategy.Config.builder().interval(1000).timeout(500).numProbes(1).build())) {

// Initial health check should work
Expand All @@ -110,7 +110,7 @@ public void testEchoStrategyWithConnectionTimeout() throws Exception {
@Test
public void testConnectionDropDuringHealthCheck() throws Exception {
JedisClientConfig config = DefaultJedisClientConfig.builder().socketTimeoutMillis(2000).build();
try (EchoStrategy strategy = new EchoStrategy(proxyHostAndPort, config,
try (PingStrategy strategy = new PingStrategy(proxyHostAndPort, config,
HealthCheckStrategy.Config.create())) {

// Initial health check
Expand Down
Loading