Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Client-side caching through URI/URL #3703

Merged
merged 18 commits into from
Feb 15, 2024
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
4 changes: 2 additions & 2 deletions src/main/java/redis/clients/jedis/JedisPooled.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public JedisPooled() {
* @param url
*/
public JedisPooled(final String url) {
this(URI.create(url));
super(url);
}

/**
Expand Down Expand Up @@ -76,7 +76,7 @@ public JedisPooled(final HostAndPort hostAndPort, final JedisClientConfig client
}

public JedisPooled(final HostAndPort hostAndPort, final JedisClientConfig clientConfig, ClientSideCache csCache) {
super(new PooledConnectionProvider(hostAndPort, clientConfig, csCache), clientConfig.getRedisProtocol(), csCache);
super(hostAndPort, clientConfig, csCache);
}

public JedisPooled(PooledObjectFactory<Connection> factory) {
Expand Down
8 changes: 6 additions & 2 deletions src/main/java/redis/clients/jedis/UnifiedJedis.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public UnifiedJedis(final URI uri) {
this(JedisURIHelper.getHostAndPort(uri), DefaultJedisClientConfig.builder()
.user(JedisURIHelper.getUser(uri)).password(JedisURIHelper.getPassword(uri))
.database(JedisURIHelper.getDBIndex(uri)).protocol(JedisURIHelper.getRedisProtocol(uri))
.ssl(JedisURIHelper.isRedisSSLScheme(uri)).build());
.ssl(JedisURIHelper.isRedisSSLScheme(uri)).build(), JedisURIHelper.getClientSideCache(uri));
}

public UnifiedJedis(final URI uri, JedisClientConfig config) {
Expand All @@ -85,13 +85,17 @@ public UnifiedJedis(final URI uri, JedisClientConfig config) {
.protocol(JedisURIHelper.getRedisProtocol(uri))
.ssl(JedisURIHelper.isRedisSSLScheme(uri)).sslSocketFactory(config.getSslSocketFactory())
.sslParameters(config.getSslParameters()).hostnameVerifier(config.getHostnameVerifier())
.build());
.build(), JedisURIHelper.getClientSideCache(uri));
}

public UnifiedJedis(HostAndPort hostAndPort, JedisClientConfig clientConfig) {
this(new PooledConnectionProvider(hostAndPort, clientConfig), clientConfig.getRedisProtocol());
}

public UnifiedJedis(HostAndPort hostAndPort, JedisClientConfig clientConfig, ClientSideCache clientSideCache) {
this(new PooledConnectionProvider(hostAndPort, clientConfig, clientSideCache), clientConfig.getRedisProtocol(), clientSideCache);
}

public UnifiedJedis(ConnectionProvider provider) {
this(new DefaultCommandExecutor(provider), provider);
}
Expand Down
89 changes: 84 additions & 5 deletions src/main/java/redis/clients/jedis/util/JedisURIHelper.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package redis.clients.jedis.util;

import java.net.URI;
import redis.clients.jedis.ClientSideCache;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Protocol;
import redis.clients.jedis.RedisProtocol;
Expand Down Expand Up @@ -54,11 +55,12 @@ public static int getDBIndex(URI uri) {
public static RedisProtocol getRedisProtocol(URI uri) {
if (uri.getQuery() == null) return null;

String[] pairs = uri.getQuery().split("&");
for (String pair : pairs) {
int idx = pair.indexOf("=");
if ("protocol".equals(pair.substring(0, idx))) {
String ver = pair.substring(idx + 1);
String[] params = uri.getQuery().split("&");
for (String param : params) {
int idx = param.indexOf("=");
if (idx < 0) continue;
if ("protocol".equals(param.substring(0, idx))) {
String ver = param.substring(idx + 1);
for (RedisProtocol proto : RedisProtocol.values()) {
if (proto.version().equals(ver)) {
return proto;
Expand All @@ -70,6 +72,83 @@ public static RedisProtocol getRedisProtocol(URI uri) {
return null; // null (default) when not defined
}

private static final Integer ZERO_INTEGER = 0;

public static ClientSideCache getClientSideCache(URI uri) {
if (uri.getQuery() == null) return null;

boolean guava = false, caffeine = false; // cache_lib
Integer maxSize = null; // cache_max_size --> 0 = disbale
Integer ttl = null; // cache_ttl --> 0 = no ttl
// cache-max-idle

String[] params = uri.getQuery().split("&");
for (String param : params) {
int idx = param.indexOf("=");
sazzad16 marked this conversation as resolved.
Show resolved Hide resolved
if (idx < 0) continue;

String key = param.substring(0, idx);
String val = param.substring(idx + 1);

switch (key) {

case "cache_lib":
switch (val) {
case "guava":
guava = true;
break;
case "caffeine":
caffeine = true;
break;
default:
throw new IllegalArgumentException("Unsupported library " + val);
}
break;

case "cache_max_size":
try {
maxSize = Integer.parseInt(val);
} catch (NumberFormatException nfe) {
throw new IllegalArgumentException("Value of cache_max_size must be an integer.", nfe);
}
break;

case "cache_ttl":
try {
ttl = Integer.parseInt(val);
} catch (NumberFormatException nfe) {
throw new IllegalArgumentException("Value of cache_ttl must be an integer denoting seconds.", nfe);
}
break;
}
}

// special cases
if (ZERO_INTEGER.equals(maxSize)) {
return null;
}
if (!guava && !caffeine && (maxSize != null || ttl != null)) {
throw new IllegalArgumentException("The cache library (guava OR caffeine) must be selected.");
Copy link
Collaborator Author

@sazzad16 sazzad16 Feb 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gerzse When user has set other cache_ params, it means they want to enable client side caching. Returning null here disables that and so it is not an option.

}
if (ZERO_INTEGER.equals(ttl)) {
ttl = null; // below, only null will be checked
}

if (guava) {
GuavaCSC.Builder guavaBuilder = GuavaCSC.builder();
if (maxSize != null) guavaBuilder.maximumSize(maxSize);
if (ttl != null) guavaBuilder.ttl(ttl);
return guavaBuilder.build();
} else if (caffeine) {
CaffeineCSC.Builder caffeineBuilder = CaffeineCSC.builder();
if (maxSize != null) caffeineBuilder.maximumSize(maxSize);
if (ttl != null) caffeineBuilder.ttl(ttl);
return caffeineBuilder.build();
}

return null; // null (default) when not defined
}

public static boolean isValid(URI uri) {
if (isEmpty(uri.getScheme()) || isEmpty(uri.getHost()) || uri.getPort() == -1) {
return false;
Expand Down
Loading