MultiDbConnectionSupplier.java
package redis.clients.jedis.mcf;
import io.github.resilience4j.circuitbreaker.CircuitBreaker.State;
import io.github.resilience4j.decorators.Decorators;
import io.github.resilience4j.decorators.Decorators.DecorateSupplier;
import redis.clients.jedis.Connection;
import redis.clients.jedis.annots.Experimental;
import redis.clients.jedis.mcf.MultiDbConnectionProvider.Database;
/**
* ConnectionProvider with built-in retry, circuit-breaker, and failover to another /database
* endpoint. With this executor users can seamlessly failover to Disaster Recovery (DR), Backup, and
* Active-Active cluster(s) by using simple configuration
*/
@Experimental
public class MultiDbConnectionSupplier extends MultiDbFailoverBase {
public MultiDbConnectionSupplier(MultiDbConnectionProvider provider) {
super(provider);
}
public Connection getConnection() {
Database database = provider.getDatabase(); // Pass this by reference for thread safety
DecorateSupplier<Connection> supplier = Decorators
.ofSupplier(() -> this.handleGetConnection(database));
supplier.withRetry(database.getRetry());
supplier.withCircuitBreaker(database.getCircuitBreaker());
supplier.withFallback(provider.getFallbackExceptionList(),
e -> this.handleDatabaseFailover(database));
try {
return supplier.decorate().get();
} catch (Exception e) {
if (database.getCircuitBreaker().getState() == State.OPEN && isActiveDatabase(database)) {
databaseFailover(database);
}
throw e;
}
}
/**
* Functional interface wrapped in retry and circuit breaker logic to handle happy path scenarios
*/
private Connection handleGetConnection(Database database) {
Connection connection = database.getConnection();
connection.ping();
return connection;
}
/**
* Functional interface wrapped in retry and circuit breaker logic to handle open circuit breaker
* failure scenarios
*/
private Connection handleDatabaseFailover(Database database) {
databaseFailover(database);
// Recursive call to the initiating method so the operation can be retried on the next database
// connection
return getConnection();
}
}