Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
8a9f876
- weighted cluster seleciton
atakavci Jun 27, 2025
d514ecf
- add builder for ClusterConfig
atakavci Jul 9, 2025
df66b1e
- fix naming
atakavci Jul 9, 2025
13757f5
clean up and mark override methods
atakavci Jul 10, 2025
ef5d83a
fix link in javadoc
atakavci Jul 10, 2025
a15fc64
fix formatting
atakavci Jul 10, 2025
cf38240
- fix double registered listeners in healtstatusmgr
atakavci Jul 14, 2025
c2fb34c
Update src/main/java/redis/clients/jedis/mcf/EchoStrategy.java
atakavci Jul 16, 2025
ade866d
- add remove endpoints
atakavci Jul 11, 2025
ca3378d
- replace cluster disabled with failbackCandidate
atakavci Jul 15, 2025
ddcec73
- remove failback candidate
atakavci Jul 16, 2025
c1b6d5f
- fix remove logic
atakavci Jul 16, 2025
ff16330
- periodic failback checks
atakavci Jul 17, 2025
c39fda1
- introduce StatusTracker with purpose of waiting initial healthcheck…
atakavci Jul 19, 2025
975ab78
- introduce forceActiveCluster by duration
atakavci Jul 19, 2025
405101e
- fix failing tests by waiting on clusters to get healthy
atakavci Jul 23, 2025
607c66d
- fix failing scenario test
atakavci Jul 23, 2025
aaac8f7
- adressing reviews and feedback
atakavci Jul 23, 2025
2ffffef
- fix formatting
atakavci Jul 23, 2025
e6e1121
- fix formatting
atakavci Jul 23, 2025
b8d4e87
- get rid of the queue and event ordering for healthstatus change in …
atakavci Jul 24, 2025
1ae7219
- replace use of reflection with helper methods
atakavci Jul 24, 2025
397f437
- introduce clusterSwitchEvent and drop clusterFailover post processor
atakavci Jul 31, 2025
ab05e6c
- introduce fastfailover using objectMaker injection into connection…
atakavci Jul 31, 2025
de034f4
- polish
atakavci Jul 31, 2025
df3d555
- cleanup
atakavci Jul 31, 2025
3352260
- improve healtcheck thread visibility
atakavci Jul 31, 2025
812979a
- introduce TrackingConnectionPool with FailFastConnectionFactory
atakavci Aug 4, 2025
0ad3bbe
- return broken source as usual
atakavci Aug 5, 2025
13cc8db
- unblock waiting threads
atakavci Aug 5, 2025
1c2b549
- failover by closing the pool
atakavci Aug 6, 2025
21a95a2
- formatting
atakavci Aug 6, 2025
984db94
- check waiters and active/idle connections to force disconnect
atakavci Aug 6, 2025
5350cfc
- add builder to trackingconnectionpool
atakavci Aug 6, 2025
03ac208
- fix failing tests due to mocked ctor for trackingConnectionPool
atakavci Aug 6, 2025
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ tags
redis-git
appendonlydir/
.DS_Store
.vscode/settings.json
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.3.15</version>
<version>1.2.12</version>
<scope>test</scope>
</dependency>
<dependency>
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/redis/clients/jedis/CommandObjects.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ public final CommandObject<String> ping() {
return PING_COMMAND_OBJECT;
}

public final CommandObject<String> echo(String msg) {
return new CommandObject<>(commandArguments(ECHO).add(msg), BuilderFactory.STRING);
}

private final CommandObject<String> FLUSHALL_COMMAND_OBJECT = new CommandObject<>(commandArguments(FLUSHALL), BuilderFactory.STRING);

public final CommandObject<String> flushAll() {
Expand Down
66 changes: 64 additions & 2 deletions src/main/java/redis/clients/jedis/Connection.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,47 @@

public class Connection implements Closeable {

public static class Builder {
private JedisSocketFactory socketFactory;
private JedisClientConfig clientConfig;
private InitializationTracker<Connection> tracker;

public Builder setSocketFactory(JedisSocketFactory socketFactory) {
this.socketFactory = socketFactory;
return this;
}

public Builder setClientConfig(JedisClientConfig clientConfig) {
this.clientConfig = clientConfig;
return this;
}

public Builder setTracker(InitializationTracker<Connection> tracker) {
this.tracker = tracker;
return this;
}

public JedisSocketFactory getSocketFactory() {
return socketFactory;
}

public JedisClientConfig getClientConfig() {
return clientConfig;
}

public InitializationTracker<Connection> getTracker() {
return tracker;
}

public Connection build() {
return new Connection(this);
}
}

public static Builder builder(){
return new Builder();
}

private ConnectionPool memberOf;
protected RedisProtocol protocol;
private final JedisSocketFactory socketFactory;
Expand Down Expand Up @@ -72,11 +113,25 @@ public Connection(final JedisSocketFactory socketFactory) {

public Connection(final JedisSocketFactory socketFactory, JedisClientConfig clientConfig) {
this.socketFactory = socketFactory;
this.soTimeout = clientConfig.getSocketTimeoutMillis();
this.infiniteSoTimeout = clientConfig.getBlockingSocketTimeoutMillis();
initializeFromClientConfig(clientConfig);
}

protected Connection(Builder builder) {
this.socketFactory = builder.getSocketFactory();
InitializationTracker<Connection> tracker = builder.getTracker();

if (tracker != null) {
tracker.add(this);
try {
initializeFromClientConfig(builder.getClientConfig());
} finally {
tracker.remove(this);
}
} else {
initializeFromClientConfig(builder.getClientConfig());
}
}

@Override
public String toString() {
return getClass().getSimpleName() + "{" + socketFactory + "}";
Expand Down Expand Up @@ -288,6 +343,10 @@ public void disconnect() {
}
}

public void forceDisconnect() throws IOException {
socket.close();
}

public boolean isConnected() {
return socket != null && socket.isBound() && !socket.isClosed() && socket.isConnected()
&& !socket.isInputShutdown() && !socket.isOutputShutdown();
Expand Down Expand Up @@ -452,6 +511,9 @@ private static boolean validateClientInfo(String info) {

protected void initializeFromClientConfig(final JedisClientConfig config) {
try {
this.soTimeout = config.getSocketTimeoutMillis();
this.infiniteSoTimeout = config.getBlockingSocketTimeoutMillis();

connect();

protocol = config.getRedisProtocol();
Expand Down
93 changes: 89 additions & 4 deletions src/main/java/redis/clients/jedis/ConnectionFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.slf4j.LoggerFactory;

import java.util.function.Supplier;
import java.util.function.UnaryOperator;

import redis.clients.jedis.annots.Experimental;
import redis.clients.jedis.authentication.AuthXManager;
Expand All @@ -21,14 +22,75 @@
*/
public class ConnectionFactory implements PooledObjectFactory<Connection> {

public static class Builder {

private JedisSocketFactory jedisSocketFactory;
private JedisClientConfig clientConfig;
private Cache cache;
private InitializationTracker<Connection> tracker;
private HostAndPort hostAndPort;

public JedisSocketFactory getJedisSocketFactory() {
return jedisSocketFactory;
}

public JedisClientConfig getClientConfig() {
return clientConfig;
}

public Cache getCache() {
return cache;
}

public InitializationTracker<Connection> getTracker() {
return tracker;
}

public Builder setJedisSocketFactory(JedisSocketFactory jedisSocketFactory) {
this.jedisSocketFactory = jedisSocketFactory;
return this;
}

public Builder setClientConfig(JedisClientConfig clientConfig) {
this.clientConfig = clientConfig;
return this;
}

public Builder setCache(Cache cache) {
this.cache = cache;
return this;
}

public Builder setTracker(InitializationTracker<Connection> tracker) {
this.tracker = tracker;
return this;
}

public Builder setHostAndPort(HostAndPort hostAndPort) {
this.hostAndPort = hostAndPort;
return this;
}

public ConnectionFactory build() {
return new ConnectionFactory(this);
}

}

public static Builder builder() {
return new Builder();
}

private static final Logger logger = LoggerFactory.getLogger(ConnectionFactory.class);

private final JedisSocketFactory jedisSocketFactory;
private final JedisClientConfig clientConfig;
private final Cache clientSideCache;
private final Supplier<Connection> objectMaker;
private Supplier<Connection> objectMaker;

private AuthXEventListener authXEventListener;

private final AuthXEventListener authXEventListener;
private InitializationTracker<Connection> tracker;

public ConnectionFactory(final HostAndPort hostAndPort) {
this(hostAndPort, DefaultJedisClientConfig.builder().build(), null);
Expand Down Expand Up @@ -56,6 +118,24 @@ private ConnectionFactory(final JedisSocketFactory jedisSocketFactory,
this.clientSideCache = csCache;
this.clientConfig = clientConfig;

initAuthXManager();
}

public ConnectionFactory(Builder builder) {
this.clientConfig = builder.getClientConfig() != null ? builder.getClientConfig()
: DefaultJedisClientConfig.builder().build();
if (builder.getJedisSocketFactory() == null) {
this.jedisSocketFactory = new DefaultJedisSocketFactory(builder.hostAndPort, this.clientConfig);
} else {
this.jedisSocketFactory = builder.getJedisSocketFactory();
}
this.clientSideCache = builder.getCache();
this.tracker = builder.getTracker();

initAuthXManager();
}

private void initAuthXManager() {
AuthXManager authXManager = clientConfig.getAuthXManager();
if (authXManager == null) {
this.objectMaker = connectionSupplier();
Expand All @@ -69,8 +149,13 @@ private ConnectionFactory(final JedisSocketFactory jedisSocketFactory,
}

private Supplier<Connection> connectionSupplier() {
return clientSideCache == null ? () -> new Connection(jedisSocketFactory, clientConfig)
: () -> new CacheConnection(jedisSocketFactory, clientConfig, clientSideCache);
Connection.Builder conBuilder = clientSideCache == null ? Connection.builder()
: CacheConnection.builder(clientSideCache);
conBuilder.setSocketFactory(jedisSocketFactory).setClientConfig(clientConfig);
if (tracker != null) {
conBuilder.setTracker(tracker);
}
return () -> conBuilder.build();
}

@Override
Expand Down
27 changes: 18 additions & 9 deletions src/main/java/redis/clients/jedis/ConnectionPool.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

import redis.clients.authentication.core.Token;
import redis.clients.jedis.annots.Experimental;
import redis.clients.jedis.authentication.AuthXManager;
import redis.clients.jedis.csc.Cache;
Expand Down Expand Up @@ -65,17 +66,25 @@ public void close() {
}
}

private void attachAuthenticationListener(AuthXManager authXManager) {
protected void attachAuthenticationListener(AuthXManager authXManager) {
this.authXManager = authXManager;
if (authXManager != null) {
authXManager.addPostAuthenticationHook(token -> {
try {
// this is to trigger validations on each connection via ConnectionFactory
evict();
} catch (Exception e) {
throw new JedisException("Failed to evict connections from pool", e);
}
});
authXManager.addPostAuthenticationHook(this::postAuthentication);
}
}

protected void detachAuthenticationListener() {
if (authXManager != null) {
authXManager.removePostAuthenticationHook(this::postAuthentication);
}
}

private void postAuthentication(Token token) {
try {
// this is to trigger validations on each connection via ConnectionFactory
evict();
} catch (Exception e) {
throw new JedisException("Failed to evict connections from pool", e);
}
}
}
6 changes: 5 additions & 1 deletion src/main/java/redis/clients/jedis/HostAndPort.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import java.io.Serializable;

public class HostAndPort implements Serializable {
import redis.clients.jedis.mcf.Endpoint;

public class HostAndPort implements Serializable, Endpoint {

private static final long serialVersionUID = -519876229978427751L;

Expand All @@ -14,10 +16,12 @@ public HostAndPort(String host, int port) {
this.port = port;
}

@Override
public String getHost() {
return host;
}

@Override
public int getPort() {
return port;
}
Expand Down
21 changes: 21 additions & 0 deletions src/main/java/redis/clients/jedis/InitializationTracker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package redis.clients.jedis;

public interface InitializationTracker<T> extends Iterable<T> {
void add(T target);
void remove(T target);

public static InitializationTracker NOOP = new InitializationTracker() {
@Override
public void add(Object target) {
}

@Override
public void remove(Object target) {
}

@Override
public java.util.Iterator iterator() {
return java.util.Collections.emptyIterator();
}
};
}
Loading
Loading