From f66697f29b0534e19e2b481813b6c0a4ce8368c1 Mon Sep 17 00:00:00 2001
From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com>
Date: Thu, 25 Jan 2024 01:05:58 +0600
Subject: [PATCH 01/16] Support TTL in client side caching (using Caffeine
library)
---
pom.xml | 6 +++
.../redis/clients/jedis/ClientSideCache.java | 48 ++++++------------
.../redis/clients/jedis/UnifiedJedis.java | 4 +-
.../redis/clients/jedis/util/CaffeineCSC.java | 50 +++++++++++++++++++
.../JedisClusterClientSideCacheTest.java | 9 ++--
.../jedis/JedisPooledClientSideCacheTest.java | 9 ++--
.../JedisSentineledClientSideCacheTest.java | 18 ++-----
.../java/redis/clients/jedis/util/MapCSC.java | 39 +++++++++++++++
8 files changed, 128 insertions(+), 55 deletions(-)
create mode 100644 src/main/java/redis/clients/jedis/util/CaffeineCSC.java
create mode 100644 src/test/java/redis/clients/jedis/util/MapCSC.java
diff --git a/pom.xml b/pom.xml
index c9fd15d2cb..96a4e122f7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -74,6 +74,12 @@
gson
2.10.1
+
+ com.github.ben-manes.caffeine
+ caffeine
+ 2.9.3
+ true
+
diff --git a/src/main/java/redis/clients/jedis/ClientSideCache.java b/src/main/java/redis/clients/jedis/ClientSideCache.java
index 62c5be28c2..482c9c0681 100644
--- a/src/main/java/redis/clients/jedis/ClientSideCache.java
+++ b/src/main/java/redis/clients/jedis/ClientSideCache.java
@@ -1,63 +1,47 @@
package redis.clients.jedis;
import java.nio.ByteBuffer;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
-
import redis.clients.jedis.exceptions.JedisException;
import redis.clients.jedis.util.SafeEncoder;
-public class ClientSideCache {
+public abstract class ClientSideCache {
- private final Map cache;
+ protected ClientSideCache() { }
- public ClientSideCache() {
- this.cache = new HashMap<>();
- }
+ public abstract void clear();
- /**
- * For testing purpose only.
- * @param map
- */
- ClientSideCache(Map map) {
- this.cache = map;
- }
+ protected abstract void remove(ByteBuffer key);
- public final void clear() {
- cache.clear();
- }
+ protected abstract void put(ByteBuffer key, Object value);
+
+ protected abstract Object get(ByteBuffer key);
- public final void invalidateKeys(List list) {
+ final void invalidateKeys(List list) {
if (list == null) {
clear();
- return;
+ } else {
+ list.forEach(this::invalidateKey);
}
-
- list.forEach(this::invalidateKey);
}
private void invalidateKey(Object key) {
if (key instanceof byte[]) {
- cache.remove(convertKey((byte[]) key));
+ remove(convertKey((byte[]) key));
} else {
throw new JedisException("" + key.getClass().getSimpleName() + " is not supported. Value: " + String.valueOf(key));
}
}
- protected void setKey(Object key, Object value) {
- cache.put(getMapKey(key), value);
- }
-
- protected T getValue(Object key) {
- return (T) getMapValue(key);
+ final void set(Object key, Object value) {
+ put(makeKey(key), value);
}
- private Object getMapValue(Object key) {
- return cache.get(getMapKey(key));
+ final T get(Object key) {
+ return (T) get(makeKey(key));
}
- private ByteBuffer getMapKey(Object key) {
+ private ByteBuffer makeKey(Object key) {
if (key instanceof byte[]) {
return convertKey((byte[]) key);
} else {
diff --git a/src/main/java/redis/clients/jedis/UnifiedJedis.java b/src/main/java/redis/clients/jedis/UnifiedJedis.java
index ba7b36b134..343b24c842 100644
--- a/src/main/java/redis/clients/jedis/UnifiedJedis.java
+++ b/src/main/java/redis/clients/jedis/UnifiedJedis.java
@@ -750,11 +750,11 @@ public String set(String key, String value, SetParams params) {
@Override
public String get(String key) {
if (clientSideCache != null) {
- String cachedValue = clientSideCache.getValue(key);
+ String cachedValue = clientSideCache.get(key);
if (cachedValue != null) return cachedValue;
String value = executeCommand(commandObjects.get(key));
- if (value != null) clientSideCache.setKey(key, value);
+ if (value != null) clientSideCache.set(key, value);
return value;
}
return executeCommand(commandObjects.get(key));
diff --git a/src/main/java/redis/clients/jedis/util/CaffeineCSC.java b/src/main/java/redis/clients/jedis/util/CaffeineCSC.java
new file mode 100644
index 0000000000..7a205f40ab
--- /dev/null
+++ b/src/main/java/redis/clients/jedis/util/CaffeineCSC.java
@@ -0,0 +1,50 @@
+package redis.clients.jedis.util;
+
+import com.github.benmanes.caffeine.cache.Cache;
+import com.github.benmanes.caffeine.cache.Caffeine;
+import java.nio.ByteBuffer;
+import java.util.concurrent.TimeUnit;
+import redis.clients.jedis.ClientSideCache;
+
+public class CaffeineCSC extends ClientSideCache {
+
+ private static final int DEFAULT_MAXIMUM_SIZE = 10_000;
+
+ private final Cache cache;
+
+ public CaffeineCSC() {
+ this(DEFAULT_MAXIMUM_SIZE);
+ }
+
+ public CaffeineCSC(int maximumSize) {
+ this(Caffeine.newBuilder().maximumSize(maximumSize).build());
+ }
+
+ public CaffeineCSC(int maximumSize, int ttlSeconds) {
+ this(Caffeine.newBuilder().maximumSize(maximumSize).expireAfterWrite(ttlSeconds, TimeUnit.SECONDS).build());
+ }
+
+ public CaffeineCSC(Cache caffeineCache) {
+ this.cache = caffeineCache;
+ }
+
+ @Override
+ public final void clear() {
+ cache.invalidateAll();
+ }
+
+ @Override
+ protected void remove(ByteBuffer key) {
+ cache.invalidate(key);
+ }
+
+ @Override
+ protected void put(ByteBuffer key, Object value) {
+ cache.put(key, value);
+ }
+
+ @Override
+ protected Object get(ByteBuffer key) {
+ return cache.getIfPresent(key);
+ }
+}
diff --git a/src/test/java/redis/clients/jedis/JedisClusterClientSideCacheTest.java b/src/test/java/redis/clients/jedis/JedisClusterClientSideCacheTest.java
index 3c8bc18c5c..8e276d9665 100644
--- a/src/test/java/redis/clients/jedis/JedisClusterClientSideCacheTest.java
+++ b/src/test/java/redis/clients/jedis/JedisClusterClientSideCacheTest.java
@@ -14,6 +14,7 @@
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.hamcrest.Matchers;
import org.junit.Test;
+import redis.clients.jedis.util.MapCSC;
public class JedisClusterClientSideCacheTest extends JedisClusterTestBase {
@@ -31,7 +32,7 @@ public class JedisClusterClientSideCacheTest extends JedisClusterTestBase {
@Test
public void simple() {
- try (JedisCluster jedis = new JedisCluster(hnp, clientConfig.get(), new ClientSideCache())) {
+ try (JedisCluster jedis = new JedisCluster(hnp, clientConfig.get(), new MapCSC())) {
jedis.set("foo", "bar");
assertEquals("bar", jedis.get("foo"));
jedis.del("foo");
@@ -42,7 +43,7 @@ public void simple() {
@Test
public void simpleWithSimpleMap() {
HashMap map = new HashMap<>();
- try (JedisCluster jedis = new JedisCluster(hnp, clientConfig.get(), new ClientSideCache(map), singleConnectionPoolConfig.get())) {
+ try (JedisCluster jedis = new JedisCluster(hnp, clientConfig.get(), new MapCSC(map), singleConnectionPoolConfig.get())) {
jedis.set("foo", "bar");
assertThat(map, Matchers.aMapWithSize(0));
assertEquals("bar", jedis.get("foo"));
@@ -60,7 +61,7 @@ public void simpleWithSimpleMap() {
@Test
public void flushAll() {
- try (JedisCluster jedis = new JedisCluster(hnp, clientConfig.get(), new ClientSideCache())) {
+ try (JedisCluster jedis = new JedisCluster(hnp, clientConfig.get(), new MapCSC())) {
jedis.set("foo", "bar");
assertEquals("bar", jedis.get("foo"));
jedis.flushAll();
@@ -71,7 +72,7 @@ public void flushAll() {
@Test
public void flushAllWithSimpleMap() {
HashMap map = new HashMap<>();
- try (JedisCluster jedis = new JedisCluster(hnp, clientConfig.get(), new ClientSideCache(map), singleConnectionPoolConfig.get())) {
+ try (JedisCluster jedis = new JedisCluster(hnp, clientConfig.get(), new MapCSC(map), singleConnectionPoolConfig.get())) {
jedis.set("foo", "bar");
assertThat(map, Matchers.aMapWithSize(0));
assertEquals("bar", jedis.get("foo"));
diff --git a/src/test/java/redis/clients/jedis/JedisPooledClientSideCacheTest.java b/src/test/java/redis/clients/jedis/JedisPooledClientSideCacheTest.java
index ad4313a4b7..805d9738d7 100644
--- a/src/test/java/redis/clients/jedis/JedisPooledClientSideCacheTest.java
+++ b/src/test/java/redis/clients/jedis/JedisPooledClientSideCacheTest.java
@@ -12,6 +12,7 @@
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import redis.clients.jedis.util.MapCSC;
public class JedisPooledClientSideCacheTest {
@@ -42,7 +43,7 @@ public void tearDown() throws Exception {
@Test
public void simple() {
- try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), new ClientSideCache())) {
+ try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), new MapCSC())) {
control.set("foo", "bar");
assertEquals("bar", jedis.get("foo"));
control.del("foo");
@@ -53,7 +54,7 @@ public void simple() {
@Test
public void simpleWithSimpleMap() {
HashMap map = new HashMap<>();
- try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), new ClientSideCache(map), singleConnectionPoolConfig.get())) {
+ try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), new MapCSC(map), singleConnectionPoolConfig.get())) {
control.set("foo", "bar");
assertThat(map, Matchers.aMapWithSize(0));
assertEquals("bar", jedis.get("foo"));
@@ -71,7 +72,7 @@ public void simpleWithSimpleMap() {
@Test
public void flushAll() {
- try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), new ClientSideCache())) {
+ try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), new MapCSC())) {
control.set("foo", "bar");
assertEquals("bar", jedis.get("foo"));
control.flushAll();
@@ -82,7 +83,7 @@ public void flushAll() {
@Test
public void flushAllWithSimpleMap() {
HashMap map = new HashMap<>();
- try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), new ClientSideCache(map), singleConnectionPoolConfig.get())) {
+ try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), new MapCSC(map), singleConnectionPoolConfig.get())) {
control.set("foo", "bar");
assertThat(map, Matchers.aMapWithSize(0));
assertEquals("bar", jedis.get("foo"));
diff --git a/src/test/java/redis/clients/jedis/JedisSentineledClientSideCacheTest.java b/src/test/java/redis/clients/jedis/JedisSentineledClientSideCacheTest.java
index 9af243ffc7..5fa5a36f4b 100644
--- a/src/test/java/redis/clients/jedis/JedisSentineledClientSideCacheTest.java
+++ b/src/test/java/redis/clients/jedis/JedisSentineledClientSideCacheTest.java
@@ -8,12 +8,11 @@
import java.util.Arrays;
import java.util.HashMap;
import java.util.Set;
-import java.util.function.Supplier;
import java.util.stream.Collectors;
-import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.hamcrest.Matchers;
import org.junit.Test;
+import redis.clients.jedis.util.MapCSC;
public class JedisSentineledClientSideCacheTest {
@@ -28,16 +27,9 @@ public class JedisSentineledClientSideCacheTest {
private static final JedisClientConfig sentinelClientConfig = DefaultJedisClientConfig.builder().resp3().build();
- private static final Supplier> singleConnectionPoolConfig
- = () -> {
- ConnectionPoolConfig poolConfig = new ConnectionPoolConfig();
- poolConfig.setMaxTotal(1);
- return poolConfig;
- };
-
@Test
public void simple() {
- try (JedisSentineled jedis = new JedisSentineled(MASTER_NAME, masterClientConfig, new ClientSideCache(), sentinels, sentinelClientConfig)) {
+ try (JedisSentineled jedis = new JedisSentineled(MASTER_NAME, masterClientConfig, new MapCSC(), sentinels, sentinelClientConfig)) {
jedis.set("foo", "bar");
assertEquals("bar", jedis.get("foo"));
jedis.del("foo");
@@ -48,7 +40,7 @@ public void simple() {
@Test
public void simpleWithSimpleMap() {
HashMap map = new HashMap<>();
- try (JedisSentineled jedis = new JedisSentineled(MASTER_NAME, masterClientConfig, new ClientSideCache(map), sentinels, sentinelClientConfig)) {
+ try (JedisSentineled jedis = new JedisSentineled(MASTER_NAME, masterClientConfig, new MapCSC(map), sentinels, sentinelClientConfig)) {
jedis.set("foo", "bar");
assertThat(map, Matchers.aMapWithSize(0));
assertEquals("bar", jedis.get("foo"));
@@ -66,7 +58,7 @@ public void simpleWithSimpleMap() {
@Test
public void flushAll() {
- try (JedisSentineled jedis = new JedisSentineled(MASTER_NAME, masterClientConfig, new ClientSideCache(), sentinels, sentinelClientConfig)) {
+ try (JedisSentineled jedis = new JedisSentineled(MASTER_NAME, masterClientConfig, new MapCSC(), sentinels, sentinelClientConfig)) {
jedis.set("foo", "bar");
assertEquals("bar", jedis.get("foo"));
jedis.flushAll();
@@ -77,7 +69,7 @@ public void flushAll() {
@Test
public void flushAllWithSimpleMap() {
HashMap map = new HashMap<>();
- try (JedisSentineled jedis = new JedisSentineled(MASTER_NAME, masterClientConfig, new ClientSideCache(map), sentinels, sentinelClientConfig)) {
+ try (JedisSentineled jedis = new JedisSentineled(MASTER_NAME, masterClientConfig, new MapCSC(map), sentinels, sentinelClientConfig)) {
jedis.set("foo", "bar");
assertThat(map, Matchers.aMapWithSize(0));
assertEquals("bar", jedis.get("foo"));
diff --git a/src/test/java/redis/clients/jedis/util/MapCSC.java b/src/test/java/redis/clients/jedis/util/MapCSC.java
new file mode 100644
index 0000000000..a9d1ef6f37
--- /dev/null
+++ b/src/test/java/redis/clients/jedis/util/MapCSC.java
@@ -0,0 +1,39 @@
+package redis.clients.jedis.util;
+
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
+import redis.clients.jedis.ClientSideCache;
+
+public class MapCSC extends ClientSideCache {
+
+ private final Map cache;
+
+ public MapCSC() {
+ this(new HashMap<>());
+ }
+
+ public MapCSC(Map map) {
+ this.cache = map;
+ }
+
+ @Override
+ public final void clear() {
+ cache.clear();
+ }
+
+ @Override
+ protected void remove(ByteBuffer key) {
+ cache.remove(key);
+ }
+
+ @Override
+ protected void put(ByteBuffer key, Object value) {
+ cache.put(key, value);
+ }
+
+ @Override
+ protected Object get(ByteBuffer key) {
+ return cache.get(key);
+ }
+}
From 322ffeb8a876ec1fabfe40145fc1cb32c94f863e Mon Sep 17 00:00:00 2001
From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com>
Date: Thu, 25 Jan 2024 19:34:08 +0600
Subject: [PATCH 02/16] Also Guava cache
---
pom.xml | 12 ++++-
.../redis/clients/jedis/util/CaffeineCSC.java | 3 +-
.../redis/clients/jedis/util/GuavaCSC.java | 51 +++++++++++++++++++
3 files changed, 64 insertions(+), 2 deletions(-)
create mode 100644 src/main/java/redis/clients/jedis/util/GuavaCSC.java
diff --git a/pom.xml b/pom.xml
index 96a4e122f7..c8c8d8149d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -74,6 +74,15 @@
gson
2.10.1
+
+
+
+
+ com.google.guava
+ guava
+ 33.0.0-jre
+ true
+
com.github.ben-manes.caffeine
caffeine
@@ -96,7 +105,8 @@
1.19.0
test
-
+
+
junit
junit
diff --git a/src/main/java/redis/clients/jedis/util/CaffeineCSC.java b/src/main/java/redis/clients/jedis/util/CaffeineCSC.java
index 7a205f40ab..d5537cc73b 100644
--- a/src/main/java/redis/clients/jedis/util/CaffeineCSC.java
+++ b/src/main/java/redis/clients/jedis/util/CaffeineCSC.java
@@ -21,7 +21,8 @@ public CaffeineCSC(int maximumSize) {
}
public CaffeineCSC(int maximumSize, int ttlSeconds) {
- this(Caffeine.newBuilder().maximumSize(maximumSize).expireAfterWrite(ttlSeconds, TimeUnit.SECONDS).build());
+ this(Caffeine.newBuilder().maximumSize(maximumSize)
+ .expireAfterWrite(ttlSeconds, TimeUnit.SECONDS).build());
}
public CaffeineCSC(Cache caffeineCache) {
diff --git a/src/main/java/redis/clients/jedis/util/GuavaCSC.java b/src/main/java/redis/clients/jedis/util/GuavaCSC.java
new file mode 100644
index 0000000000..b4e31caa62
--- /dev/null
+++ b/src/main/java/redis/clients/jedis/util/GuavaCSC.java
@@ -0,0 +1,51 @@
+package redis.clients.jedis.util;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import java.nio.ByteBuffer;
+import java.util.concurrent.TimeUnit;
+import redis.clients.jedis.ClientSideCache;
+
+public class GuavaCSC extends ClientSideCache {
+
+ private static final int DEFAULT_MAXIMUM_SIZE = 10_000;
+
+ private final Cache cache;
+
+ public GuavaCSC() {
+ this(DEFAULT_MAXIMUM_SIZE);
+ }
+
+ public GuavaCSC(int maximumSize) {
+ this(CacheBuilder.newBuilder().maximumSize(maximumSize).build());
+ }
+
+ public GuavaCSC(int maximumSize, int ttlSeconds) {
+ this(CacheBuilder.newBuilder().maximumSize(maximumSize)
+ .expireAfterWrite(ttlSeconds, TimeUnit.SECONDS).build());
+ }
+
+ public GuavaCSC(Cache caffeineCache) {
+ this.cache = caffeineCache;
+ }
+
+ @Override
+ public final void clear() {
+ cache.invalidateAll();
+ }
+
+ @Override
+ protected void remove(ByteBuffer key) {
+ cache.invalidate(key);
+ }
+
+ @Override
+ protected void put(ByteBuffer key, Object value) {
+ cache.put(key, value);
+ }
+
+ @Override
+ protected Object get(ByteBuffer key) {
+ return cache.getIfPresent(key);
+ }
+}
From 2ef437622c218088dcb0bc66e677714dd1544925 Mon Sep 17 00:00:00 2001
From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com>
Date: Thu, 25 Jan 2024 20:29:05 +0600
Subject: [PATCH 03/16] format pom.xml
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index c8c8d8149d..1fcb758640 100644
--- a/pom.xml
+++ b/pom.xml
@@ -106,7 +106,7 @@
test
-
+
junit
junit
From 9f160e2192a1e6eb5e8df701b11f58f7483cd94c Mon Sep 17 00:00:00 2001
From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com>
Date: Sun, 28 Jan 2024 13:58:10 +0600
Subject: [PATCH 04/16] Client-side caching by command arguments
TODO: Compute hash code.
---
.../redis/clients/jedis/ClientSideCache.java | 103 +++++++++++++-----
.../clients/jedis/JedisClusterInfoCache.java | 2 +-
.../redis/clients/jedis/UnifiedJedis.java | 18 +--
.../SentineledConnectionProvider.java | 2 +-
.../redis/clients/jedis/util/CaffeineCSC.java | 19 ++--
.../redis/clients/jedis/util/GuavaCSC.java | 21 ++--
.../JedisClusterClientSideCacheTest.java | 4 +-
.../jedis/JedisPooledClientSideCacheTest.java | 4 +-
.../JedisSentineledClientSideCacheTest.java | 4 +-
.../java/redis/clients/jedis/util/MapCSC.java | 23 ++--
10 files changed, 125 insertions(+), 75 deletions(-)
diff --git a/src/main/java/redis/clients/jedis/ClientSideCache.java b/src/main/java/redis/clients/jedis/ClientSideCache.java
index 482c9c0681..063087cff5 100644
--- a/src/main/java/redis/clients/jedis/ClientSideCache.java
+++ b/src/main/java/redis/clients/jedis/ClientSideCache.java
@@ -1,55 +1,108 @@
package redis.clients.jedis;
import java.nio.ByteBuffer;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
-import redis.clients.jedis.exceptions.JedisException;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.function.Function;
import redis.clients.jedis.util.SafeEncoder;
public abstract class ClientSideCache {
- protected ClientSideCache() { }
+ private final Map> keyHashes;
+ private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
+ private final Lock readLock = rwl.readLock();
+ private final Lock writeLock = rwl.writeLock();
- public abstract void clear();
+ protected ClientSideCache() {
+ this.keyHashes = new ConcurrentHashMap<>();
+ }
+
+ protected ClientSideCache(Map> keyHashes) {
+ this.keyHashes = keyHashes;
+ }
+
+ public abstract void invalidateAll();
- protected abstract void remove(ByteBuffer key);
+ protected abstract void invalidateAll(Iterable hashes);
- protected abstract void put(ByteBuffer key, Object value);
+ protected abstract void put(long hash, Object value);
- protected abstract Object get(ByteBuffer key);
+ protected abstract Object get(long hash);
final void invalidateKeys(List list) {
if (list == null) {
- clear();
- } else {
- list.forEach(this::invalidateKey);
+ invalidateAll();
+ return;
}
+
+ Set hashes = new HashSet<>();
+ list.forEach(key -> hashes.addAll(getHashes(key)));
+ invalidateAll(hashes);
}
- private void invalidateKey(Object key) {
- if (key instanceof byte[]) {
- remove(convertKey((byte[]) key));
- } else {
- throw new JedisException("" + key.getClass().getSimpleName() + " is not supported. Value: " + String.valueOf(key));
+ private Set getHashes(Object key) {
+ if (!(key instanceof byte[])) {
+ throw new AssertionError("" + key.getClass().getSimpleName() + " is not supported. Value: " + String.valueOf(key));
+ }
+
+ final ByteBuffer mapKey = makeKey((byte[]) key);
+ readLock.lock();
+ try {
+ Set hashes = keyHashes.get(mapKey);
+ return hashes != null ? hashes : Collections.emptySet();
+ } finally {
+ readLock.unlock();
}
}
- final void set(Object key, Object value) {
- put(makeKey(key), value);
+ final T getValue(Function, T> loader, CommandObject command, String... keys) {
+
+ final long hash = getHash(command);
+
+ T value = (T) get(hash);
+ if (value != null) {
+ return value;
+ }
+
+ value = loader.apply(command);
+ if (value != null) {
+ writeLock.lock();
+ try {
+ put(hash, value);
+ for (String key : keys) {
+ ByteBuffer mapKey = makeKey(key);
+ if (keyHashes.containsKey(mapKey)) {
+ keyHashes.get(mapKey).add(hash);
+ } else {
+ Set set = new HashSet<>();
+ set.add(hash);
+ keyHashes.put(mapKey, set);
+ }
+ }
+ } finally {
+ writeLock.unlock();
+ }
+ }
+
+ return value;
}
- final T get(Object key) {
- return (T) get(makeKey(key));
+ private long getHash(CommandObject command) {
+ // TODO:
+ return 0;
}
- private ByteBuffer makeKey(Object key) {
- if (key instanceof byte[]) {
- return convertKey((byte[]) key);
- } else {
- return convertKey(SafeEncoder.encode(String.valueOf(key)));
- }
+ private ByteBuffer makeKey(String key) {
+ return makeKey(SafeEncoder.encode(key));
}
- private static ByteBuffer convertKey(byte[] b) {
+ private static ByteBuffer makeKey(byte[] b) {
return ByteBuffer.wrap(b);
}
}
diff --git a/src/main/java/redis/clients/jedis/JedisClusterInfoCache.java b/src/main/java/redis/clients/jedis/JedisClusterInfoCache.java
index 5646dbfb59..9402b150ba 100644
--- a/src/main/java/redis/clients/jedis/JedisClusterInfoCache.java
+++ b/src/main/java/redis/clients/jedis/JedisClusterInfoCache.java
@@ -227,7 +227,7 @@ private void discoverClusterSlots(Connection jedis) {
Arrays.fill(slots, null);
Arrays.fill(slotNodes, null);
if (clientSideCache != null) {
- clientSideCache.clear();
+ clientSideCache.invalidateAll();
}
Set hostAndPortKeys = new HashSet<>();
diff --git a/src/main/java/redis/clients/jedis/UnifiedJedis.java b/src/main/java/redis/clients/jedis/UnifiedJedis.java
index 343b24c842..c7936bfb62 100644
--- a/src/main/java/redis/clients/jedis/UnifiedJedis.java
+++ b/src/main/java/redis/clients/jedis/UnifiedJedis.java
@@ -295,6 +295,14 @@ public void setBroadcastAndRoundRobinConfig(JedisBroadcastAndRoundRobinConfig co
this.commandObjects.setBroadcastAndRoundRobinConfig(this.broadcastAndRoundRobinConfig);
}
+ private T executeClientSideCacheCommand(CommandObject command) {
+ if (clientSideCache == null) {
+ return executeCommand(command);
+ }
+
+ return clientSideCache.getValue((cmd) -> executeCommand(cmd), command);
+ }
+
public String ping() {
return checkAndBroadcastCommand(commandObjects.ping());
}
@@ -749,15 +757,7 @@ public String set(String key, String value, SetParams params) {
@Override
public String get(String key) {
- if (clientSideCache != null) {
- String cachedValue = clientSideCache.get(key);
- if (cachedValue != null) return cachedValue;
-
- String value = executeCommand(commandObjects.get(key));
- if (value != null) clientSideCache.set(key, value);
- return value;
- }
- return executeCommand(commandObjects.get(key));
+ return executeClientSideCacheCommand(commandObjects.get(key));
}
@Override
diff --git a/src/main/java/redis/clients/jedis/providers/SentineledConnectionProvider.java b/src/main/java/redis/clients/jedis/providers/SentineledConnectionProvider.java
index e335803b62..ae883e2af3 100644
--- a/src/main/java/redis/clients/jedis/providers/SentineledConnectionProvider.java
+++ b/src/main/java/redis/clients/jedis/providers/SentineledConnectionProvider.java
@@ -128,7 +128,7 @@ private void initMaster(HostAndPort master) {
pool = newPool;
LOG.info("Created connection pool to master at {}.", master);
if (clientSideCache != null) {
- clientSideCache.clear();
+ clientSideCache.invalidateAll();
}
if (existingPool != null) {
diff --git a/src/main/java/redis/clients/jedis/util/CaffeineCSC.java b/src/main/java/redis/clients/jedis/util/CaffeineCSC.java
index d5537cc73b..c3364168c7 100644
--- a/src/main/java/redis/clients/jedis/util/CaffeineCSC.java
+++ b/src/main/java/redis/clients/jedis/util/CaffeineCSC.java
@@ -2,7 +2,6 @@
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
-import java.nio.ByteBuffer;
import java.util.concurrent.TimeUnit;
import redis.clients.jedis.ClientSideCache;
@@ -10,7 +9,7 @@ public class CaffeineCSC extends ClientSideCache {
private static final int DEFAULT_MAXIMUM_SIZE = 10_000;
- private final Cache cache;
+ private final Cache cache;
public CaffeineCSC() {
this(DEFAULT_MAXIMUM_SIZE);
@@ -25,27 +24,27 @@ public CaffeineCSC(int maximumSize, int ttlSeconds) {
.expireAfterWrite(ttlSeconds, TimeUnit.SECONDS).build());
}
- public CaffeineCSC(Cache caffeineCache) {
+ public CaffeineCSC(Cache caffeineCache) {
this.cache = caffeineCache;
}
@Override
- public final void clear() {
+ public final void invalidateAll() {
cache.invalidateAll();
}
@Override
- protected void remove(ByteBuffer key) {
- cache.invalidate(key);
+ protected void invalidateAll(Iterable hashes) {
+ cache.invalidateAll(hashes);
}
@Override
- protected void put(ByteBuffer key, Object value) {
- cache.put(key, value);
+ protected void put(long hash, Object value) {
+ cache.put(hash, value);
}
@Override
- protected Object get(ByteBuffer key) {
- return cache.getIfPresent(key);
+ protected Object get(long hash) {
+ return cache.getIfPresent(hash);
}
}
diff --git a/src/main/java/redis/clients/jedis/util/GuavaCSC.java b/src/main/java/redis/clients/jedis/util/GuavaCSC.java
index b4e31caa62..e51e0c25f8 100644
--- a/src/main/java/redis/clients/jedis/util/GuavaCSC.java
+++ b/src/main/java/redis/clients/jedis/util/GuavaCSC.java
@@ -2,7 +2,6 @@
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
-import java.nio.ByteBuffer;
import java.util.concurrent.TimeUnit;
import redis.clients.jedis.ClientSideCache;
@@ -10,7 +9,7 @@ public class GuavaCSC extends ClientSideCache {
private static final int DEFAULT_MAXIMUM_SIZE = 10_000;
- private final Cache cache;
+ private final Cache cache;
public GuavaCSC() {
this(DEFAULT_MAXIMUM_SIZE);
@@ -25,27 +24,27 @@ public GuavaCSC(int maximumSize, int ttlSeconds) {
.expireAfterWrite(ttlSeconds, TimeUnit.SECONDS).build());
}
- public GuavaCSC(Cache caffeineCache) {
- this.cache = caffeineCache;
+ public GuavaCSC(Cache guavaCache) {
+ this.cache = guavaCache;
}
@Override
- public final void clear() {
+ public final void invalidateAll() {
cache.invalidateAll();
}
@Override
- protected void remove(ByteBuffer key) {
- cache.invalidate(key);
+ protected void invalidateAll(Iterable hashes) {
+ cache.invalidateAll(hashes);
}
@Override
- protected void put(ByteBuffer key, Object value) {
- cache.put(key, value);
+ protected void put(long hash, Object value) {
+ cache.put(hash, value);
}
@Override
- protected Object get(ByteBuffer key) {
- return cache.getIfPresent(key);
+ protected Object get(long hash) {
+ return cache.getIfPresent(hash);
}
}
diff --git a/src/test/java/redis/clients/jedis/JedisClusterClientSideCacheTest.java b/src/test/java/redis/clients/jedis/JedisClusterClientSideCacheTest.java
index 8e276d9665..2f11af837b 100644
--- a/src/test/java/redis/clients/jedis/JedisClusterClientSideCacheTest.java
+++ b/src/test/java/redis/clients/jedis/JedisClusterClientSideCacheTest.java
@@ -42,7 +42,7 @@ public void simple() {
@Test
public void simpleWithSimpleMap() {
- HashMap map = new HashMap<>();
+ HashMap map = new HashMap<>();
try (JedisCluster jedis = new JedisCluster(hnp, clientConfig.get(), new MapCSC(map), singleConnectionPoolConfig.get())) {
jedis.set("foo", "bar");
assertThat(map, Matchers.aMapWithSize(0));
@@ -71,7 +71,7 @@ public void flushAll() {
@Test
public void flushAllWithSimpleMap() {
- HashMap map = new HashMap<>();
+ HashMap map = new HashMap<>();
try (JedisCluster jedis = new JedisCluster(hnp, clientConfig.get(), new MapCSC(map), singleConnectionPoolConfig.get())) {
jedis.set("foo", "bar");
assertThat(map, Matchers.aMapWithSize(0));
diff --git a/src/test/java/redis/clients/jedis/JedisPooledClientSideCacheTest.java b/src/test/java/redis/clients/jedis/JedisPooledClientSideCacheTest.java
index 805d9738d7..b5741454db 100644
--- a/src/test/java/redis/clients/jedis/JedisPooledClientSideCacheTest.java
+++ b/src/test/java/redis/clients/jedis/JedisPooledClientSideCacheTest.java
@@ -53,7 +53,7 @@ public void simple() {
@Test
public void simpleWithSimpleMap() {
- HashMap map = new HashMap<>();
+ HashMap map = new HashMap<>();
try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), new MapCSC(map), singleConnectionPoolConfig.get())) {
control.set("foo", "bar");
assertThat(map, Matchers.aMapWithSize(0));
@@ -82,7 +82,7 @@ public void flushAll() {
@Test
public void flushAllWithSimpleMap() {
- HashMap map = new HashMap<>();
+ HashMap map = new HashMap<>();
try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), new MapCSC(map), singleConnectionPoolConfig.get())) {
control.set("foo", "bar");
assertThat(map, Matchers.aMapWithSize(0));
diff --git a/src/test/java/redis/clients/jedis/JedisSentineledClientSideCacheTest.java b/src/test/java/redis/clients/jedis/JedisSentineledClientSideCacheTest.java
index 5fa5a36f4b..de20a356f9 100644
--- a/src/test/java/redis/clients/jedis/JedisSentineledClientSideCacheTest.java
+++ b/src/test/java/redis/clients/jedis/JedisSentineledClientSideCacheTest.java
@@ -39,7 +39,7 @@ public void simple() {
@Test
public void simpleWithSimpleMap() {
- HashMap map = new HashMap<>();
+ HashMap map = new HashMap<>();
try (JedisSentineled jedis = new JedisSentineled(MASTER_NAME, masterClientConfig, new MapCSC(map), sentinels, sentinelClientConfig)) {
jedis.set("foo", "bar");
assertThat(map, Matchers.aMapWithSize(0));
@@ -68,7 +68,7 @@ public void flushAll() {
@Test
public void flushAllWithSimpleMap() {
- HashMap map = new HashMap<>();
+ HashMap map = new HashMap<>();
try (JedisSentineled jedis = new JedisSentineled(MASTER_NAME, masterClientConfig, new MapCSC(map), sentinels, sentinelClientConfig)) {
jedis.set("foo", "bar");
assertThat(map, Matchers.aMapWithSize(0));
diff --git a/src/test/java/redis/clients/jedis/util/MapCSC.java b/src/test/java/redis/clients/jedis/util/MapCSC.java
index a9d1ef6f37..1db1a64810 100644
--- a/src/test/java/redis/clients/jedis/util/MapCSC.java
+++ b/src/test/java/redis/clients/jedis/util/MapCSC.java
@@ -1,39 +1,38 @@
package redis.clients.jedis.util;
-import java.nio.ByteBuffer;
-import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import redis.clients.jedis.ClientSideCache;
public class MapCSC extends ClientSideCache {
- private final Map cache;
+ private final Map cache;
public MapCSC() {
- this(new HashMap<>());
+ this(new ConcurrentHashMap<>());
}
- public MapCSC(Map map) {
+ public MapCSC(Map map) {
this.cache = map;
}
@Override
- public final void clear() {
+ public final void invalidateAll() {
cache.clear();
}
@Override
- protected void remove(ByteBuffer key) {
- cache.remove(key);
+ protected void invalidateAll(Iterable hashes) {
+ hashes.forEach(hash -> cache.remove(hash));
}
@Override
- protected void put(ByteBuffer key, Object value) {
- cache.put(key, value);
+ protected void put(long hash, Object value) {
+ cache.put(hash, value);
}
@Override
- protected Object get(ByteBuffer key) {
- return cache.get(key);
+ protected Object get(long hash) {
+ return cache.get(hash);
}
}
From 3827e7d7dc98480d28f0e1b67559d288a94bf31a Mon Sep 17 00:00:00 2001
From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com>
Date: Sun, 28 Jan 2024 16:08:10 +0600
Subject: [PATCH 05/16] send keys
---
src/main/java/redis/clients/jedis/UnifiedJedis.java | 6 +++---
.../clients/jedis/JedisClusterClientSideCacheTest.java | 1 -
.../redis/clients/jedis/JedisPooledClientSideCacheTest.java | 1 -
.../clients/jedis/JedisSentineledClientSideCacheTest.java | 1 -
4 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/src/main/java/redis/clients/jedis/UnifiedJedis.java b/src/main/java/redis/clients/jedis/UnifiedJedis.java
index c7936bfb62..3a2dec9d77 100644
--- a/src/main/java/redis/clients/jedis/UnifiedJedis.java
+++ b/src/main/java/redis/clients/jedis/UnifiedJedis.java
@@ -295,12 +295,12 @@ public void setBroadcastAndRoundRobinConfig(JedisBroadcastAndRoundRobinConfig co
this.commandObjects.setBroadcastAndRoundRobinConfig(this.broadcastAndRoundRobinConfig);
}
- private T executeClientSideCacheCommand(CommandObject command) {
+ private T executeClientSideCacheCommand(CommandObject command, String... keys) {
if (clientSideCache == null) {
return executeCommand(command);
}
- return clientSideCache.getValue((cmd) -> executeCommand(cmd), command);
+ return clientSideCache.getValue((cmd) -> executeCommand(cmd), command, keys);
}
public String ping() {
@@ -757,7 +757,7 @@ public String set(String key, String value, SetParams params) {
@Override
public String get(String key) {
- return executeClientSideCacheCommand(commandObjects.get(key));
+ return executeClientSideCacheCommand(commandObjects.get(key), key);
}
@Override
diff --git a/src/test/java/redis/clients/jedis/JedisClusterClientSideCacheTest.java b/src/test/java/redis/clients/jedis/JedisClusterClientSideCacheTest.java
index 2f11af837b..60ddf002d7 100644
--- a/src/test/java/redis/clients/jedis/JedisClusterClientSideCacheTest.java
+++ b/src/test/java/redis/clients/jedis/JedisClusterClientSideCacheTest.java
@@ -4,7 +4,6 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
-import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Set;
diff --git a/src/test/java/redis/clients/jedis/JedisPooledClientSideCacheTest.java b/src/test/java/redis/clients/jedis/JedisPooledClientSideCacheTest.java
index b5741454db..2e641e0f3a 100644
--- a/src/test/java/redis/clients/jedis/JedisPooledClientSideCacheTest.java
+++ b/src/test/java/redis/clients/jedis/JedisPooledClientSideCacheTest.java
@@ -4,7 +4,6 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
-import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.function.Supplier;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
diff --git a/src/test/java/redis/clients/jedis/JedisSentineledClientSideCacheTest.java b/src/test/java/redis/clients/jedis/JedisSentineledClientSideCacheTest.java
index de20a356f9..9e5f720933 100644
--- a/src/test/java/redis/clients/jedis/JedisSentineledClientSideCacheTest.java
+++ b/src/test/java/redis/clients/jedis/JedisSentineledClientSideCacheTest.java
@@ -4,7 +4,6 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
-import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Set;
From e910168f2cbdef84b20abb18daa5056f607e5b52 Mon Sep 17 00:00:00 2001
From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com>
Date: Tue, 30 Jan 2024 16:20:30 +0600
Subject: [PATCH 06/16] todo comment for clean-up
---
src/main/java/redis/clients/jedis/ClientSideCache.java | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/main/java/redis/clients/jedis/ClientSideCache.java b/src/main/java/redis/clients/jedis/ClientSideCache.java
index 063087cff5..d21170afe3 100644
--- a/src/main/java/redis/clients/jedis/ClientSideCache.java
+++ b/src/main/java/redis/clients/jedis/ClientSideCache.java
@@ -14,7 +14,7 @@
public abstract class ClientSideCache {
- private final Map> keyHashes;
+ private final Map> keyHashes; // TODO: clean-up
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private final Lock readLock = rwl.readLock();
private final Lock writeLock = rwl.writeLock();
@@ -44,6 +44,7 @@ final void invalidateKeys(List list) {
Set hashes = new HashSet<>();
list.forEach(key -> hashes.addAll(getHashes(key)));
invalidateAll(hashes);
+ // TODO: clean-up keyHashes
}
private Set getHashes(Object key) {
From 0ba4d7d3f0654c330f76140545062e31780bd8bb Mon Sep 17 00:00:00 2001
From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com>
Date: Tue, 30 Jan 2024 16:24:16 +0600
Subject: [PATCH 07/16] rename method to invalidate
---
src/main/java/redis/clients/jedis/ClientSideCache.java | 2 +-
src/main/java/redis/clients/jedis/Protocol.java | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/main/java/redis/clients/jedis/ClientSideCache.java b/src/main/java/redis/clients/jedis/ClientSideCache.java
index d21170afe3..616fe7d7b5 100644
--- a/src/main/java/redis/clients/jedis/ClientSideCache.java
+++ b/src/main/java/redis/clients/jedis/ClientSideCache.java
@@ -35,7 +35,7 @@ protected ClientSideCache(Map> keyHashes) {
protected abstract Object get(long hash);
- final void invalidateKeys(List list) {
+ final void invalidate(List list) {
if (list == null) {
invalidateAll();
return;
diff --git a/src/main/java/redis/clients/jedis/Protocol.java b/src/main/java/redis/clients/jedis/Protocol.java
index 4af1261cd4..4bd82fec1e 100644
--- a/src/main/java/redis/clients/jedis/Protocol.java
+++ b/src/main/java/redis/clients/jedis/Protocol.java
@@ -248,7 +248,7 @@ private static void processPush(final RedisInputStream is, ClientSideCache cache
//System.out.println("PUSH: " + SafeEncoder.encodeObject(list));
if (list.size() == 2 && list.get(0) instanceof byte[]
&& Arrays.equals(INVALIDATE_BYTES, (byte[]) list.get(0))) {
- cache.invalidateKeys((List) list.get(1));
+ cache.invalidate((List) list.get(1));
}
}
From e3a5900fa32f931373c02d421fa1e6f85762c0ce Mon Sep 17 00:00:00 2001
From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com>
Date: Wed, 31 Jan 2024 00:41:31 +0600
Subject: [PATCH 08/16] Client-side caching by hashing command arguments
---
.../redis/clients/jedis/ClientSideCache.java | 17 ++--
.../redis/clients/jedis/util/CaffeineCSC.java | 12 +++
.../redis/clients/jedis/util/GuavaCSC.java | 82 +++++++++++++++----
.../java/redis/clients/jedis/util/MapCSC.java | 12 +++
4 files changed, 97 insertions(+), 26 deletions(-)
diff --git a/src/main/java/redis/clients/jedis/ClientSideCache.java b/src/main/java/redis/clients/jedis/ClientSideCache.java
index 616fe7d7b5..2b15fb75df 100644
--- a/src/main/java/redis/clients/jedis/ClientSideCache.java
+++ b/src/main/java/redis/clients/jedis/ClientSideCache.java
@@ -23,18 +23,10 @@ protected ClientSideCache() {
this.keyHashes = new ConcurrentHashMap<>();
}
- protected ClientSideCache(Map> keyHashes) {
- this.keyHashes = keyHashes;
- }
-
public abstract void invalidateAll();
protected abstract void invalidateAll(Iterable hashes);
- protected abstract void put(long hash, Object value);
-
- protected abstract Object get(long hash);
-
final void invalidate(List list) {
if (list == null) {
invalidateAll();
@@ -62,6 +54,10 @@ private Set getHashes(Object key) {
}
}
+ protected abstract void put(long hash, Object value);
+
+ protected abstract Object get(long hash);
+
final T getValue(Function, T> loader, CommandObject command, String... keys) {
final long hash = getHash(command);
@@ -94,10 +90,7 @@ final T getValue(Function, T> loader, CommandObject comm
return value;
}
- private long getHash(CommandObject command) {
- // TODO:
- return 0;
- }
+ protected abstract long getHash(CommandObject command);
private ByteBuffer makeKey(String key) {
return makeKey(SafeEncoder.encode(key));
diff --git a/src/main/java/redis/clients/jedis/util/CaffeineCSC.java b/src/main/java/redis/clients/jedis/util/CaffeineCSC.java
index c3364168c7..c12f7a475b 100644
--- a/src/main/java/redis/clients/jedis/util/CaffeineCSC.java
+++ b/src/main/java/redis/clients/jedis/util/CaffeineCSC.java
@@ -2,8 +2,11 @@
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
+import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import redis.clients.jedis.ClientSideCache;
+import redis.clients.jedis.CommandObject;
+import redis.clients.jedis.args.Rawable;
public class CaffeineCSC extends ClientSideCache {
@@ -47,4 +50,13 @@ protected void put(long hash, Object value) {
protected Object get(long hash) {
return cache.getIfPresent(hash);
}
+
+ @Override // TODO:
+ protected final long getHash(CommandObject command) {
+ long result = 1;
+ for (Rawable raw : command.getArguments()) {
+ result = 31 * result + Arrays.hashCode(raw.getRaw());
+ }
+ return 31 * result + command.getBuilder().hashCode();
+ }
}
diff --git a/src/main/java/redis/clients/jedis/util/GuavaCSC.java b/src/main/java/redis/clients/jedis/util/GuavaCSC.java
index e51e0c25f8..282c03790e 100644
--- a/src/main/java/redis/clients/jedis/util/GuavaCSC.java
+++ b/src/main/java/redis/clients/jedis/util/GuavaCSC.java
@@ -2,30 +2,25 @@
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
+import com.google.common.hash.HashFunction;
+import com.google.common.hash.Hasher;
+import java.time.Duration;
import java.util.concurrent.TimeUnit;
import redis.clients.jedis.ClientSideCache;
+import redis.clients.jedis.CommandObject;
public class GuavaCSC extends ClientSideCache {
private static final int DEFAULT_MAXIMUM_SIZE = 10_000;
+ private static final int DEFAULT_EXPIRE_MINUTES = 5;
+ private static final HashFunction DEFAULT_FUNCTION = com.google.common.hash.Hashing.fingerprint2011();
private final Cache cache;
+ private final HashFunction function;
- public GuavaCSC() {
- this(DEFAULT_MAXIMUM_SIZE);
- }
-
- public GuavaCSC(int maximumSize) {
- this(CacheBuilder.newBuilder().maximumSize(maximumSize).build());
- }
-
- public GuavaCSC(int maximumSize, int ttlSeconds) {
- this(CacheBuilder.newBuilder().maximumSize(maximumSize)
- .expireAfterWrite(ttlSeconds, TimeUnit.SECONDS).build());
- }
-
- public GuavaCSC(Cache guavaCache) {
+ public GuavaCSC(Cache guavaCache, HashFunction hashFunction) {
this.cache = guavaCache;
+ this.function = hashFunction;
}
@Override
@@ -47,4 +42,63 @@ protected void put(long hash, Object value) {
protected Object get(long hash) {
return cache.getIfPresent(hash);
}
+
+ @Override
+ protected final long getHash(CommandObject command) {
+ Hasher hasher = function.newHasher();
+ command.getArguments().forEach(raw -> hasher.putBytes(raw.getRaw()));
+ hasher.putInt(command.getBuilder().hashCode());
+ return hasher.hash().asLong();
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+
+ private long maximumSize = DEFAULT_MAXIMUM_SIZE;
+ private Duration expireDuration = null;
+ private long expireTime = DEFAULT_EXPIRE_MINUTES;
+ private TimeUnit expireTimeUnit = TimeUnit.MINUTES;
+
+ private HashFunction hashFunction = DEFAULT_FUNCTION;
+
+ private Builder() { }
+
+ public Builder maximumSize(int size) {
+ this.maximumSize = size;
+ return this;
+ }
+
+ public Builder ttl(Duration duration) {
+ this.expireDuration = duration;
+ return this;
+ }
+
+ public Builder ttl(long time, TimeUnit unit) {
+ this.expireTime = time;
+ this.expireTimeUnit = unit;
+ return this;
+ }
+
+ public Builder hashFunction(HashFunction function) {
+ this.hashFunction = function;
+ return this;
+ }
+
+ public GuavaCSC build() {
+ CacheBuilder cb = CacheBuilder.newBuilder();
+
+ cb.maximumSize(maximumSize);
+
+ if (expireDuration != null) {
+ cb.expireAfterWrite(expireDuration);
+ } else {
+ cb.expireAfterWrite(expireTime, expireTimeUnit);
+ }
+
+ return new GuavaCSC(cb.build(), hashFunction);
+ }
+ }
}
diff --git a/src/test/java/redis/clients/jedis/util/MapCSC.java b/src/test/java/redis/clients/jedis/util/MapCSC.java
index 1db1a64810..0915fd9050 100644
--- a/src/test/java/redis/clients/jedis/util/MapCSC.java
+++ b/src/test/java/redis/clients/jedis/util/MapCSC.java
@@ -1,8 +1,11 @@
package redis.clients.jedis.util;
+import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import redis.clients.jedis.ClientSideCache;
+import redis.clients.jedis.CommandObject;
+import redis.clients.jedis.args.Rawable;
public class MapCSC extends ClientSideCache {
@@ -35,4 +38,13 @@ protected void put(long hash, Object value) {
protected Object get(long hash) {
return cache.get(hash);
}
+
+ @Override
+ protected final long getHash(CommandObject command) {
+ long result = 1;
+ for (Rawable raw : command.getArguments()) {
+ result = 31 * result + Arrays.hashCode(raw.getRaw());
+ }
+ return 31 * result + command.getBuilder().hashCode();
+ }
}
From d7720a1386b9ad633925cda32eddcf848f39bc72 Mon Sep 17 00:00:00 2001
From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com>
Date: Thu, 1 Feb 2024 00:47:01 +0600
Subject: [PATCH 09/16] Hash command arguments for CaffeineCSC using OpenHFT
hashing
---
pom.xml | 6 ++
.../redis/clients/jedis/util/CaffeineCSC.java | 71 ++++++++++++++-----
.../redis/clients/jedis/util/GuavaCSC.java | 28 +++-----
3 files changed, 66 insertions(+), 39 deletions(-)
diff --git a/pom.xml b/pom.xml
index 1fcb758640..e6ff5bc70b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -89,6 +89,12 @@
2.9.3
true
+
+ net.openhft
+ zero-allocation-hashing
+ 0.16
+ true
+
diff --git a/src/main/java/redis/clients/jedis/util/CaffeineCSC.java b/src/main/java/redis/clients/jedis/util/CaffeineCSC.java
index c12f7a475b..36f354bc4a 100644
--- a/src/main/java/redis/clients/jedis/util/CaffeineCSC.java
+++ b/src/main/java/redis/clients/jedis/util/CaffeineCSC.java
@@ -2,8 +2,8 @@
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
-import java.util.Arrays;
import java.util.concurrent.TimeUnit;
+import net.openhft.hashing.LongHashFunction;
import redis.clients.jedis.ClientSideCache;
import redis.clients.jedis.CommandObject;
import redis.clients.jedis.args.Rawable;
@@ -11,24 +11,15 @@
public class CaffeineCSC extends ClientSideCache {
private static final int DEFAULT_MAXIMUM_SIZE = 10_000;
+ private static final int DEFAULT_EXPIRE_SECONDS = 100;
+ private static final LongHashFunction DEFAULT_HASH_FUNCTION = LongHashFunction.xx3();
private final Cache cache;
+ private final LongHashFunction function;
- public CaffeineCSC() {
- this(DEFAULT_MAXIMUM_SIZE);
- }
-
- public CaffeineCSC(int maximumSize) {
- this(Caffeine.newBuilder().maximumSize(maximumSize).build());
- }
-
- public CaffeineCSC(int maximumSize, int ttlSeconds) {
- this(Caffeine.newBuilder().maximumSize(maximumSize)
- .expireAfterWrite(ttlSeconds, TimeUnit.SECONDS).build());
- }
-
- public CaffeineCSC(Cache caffeineCache) {
+ public CaffeineCSC(Cache caffeineCache, LongHashFunction hashFunction) {
this.cache = caffeineCache;
+ this.function = hashFunction;
}
@Override
@@ -51,12 +42,54 @@ protected Object get(long hash) {
return cache.getIfPresent(hash);
}
- @Override // TODO:
+ @Override
protected final long getHash(CommandObject command) {
- long result = 1;
+ long[] nums = new long[command.getArguments().size() + 1];
+ int idx = 0;
for (Rawable raw : command.getArguments()) {
- result = 31 * result + Arrays.hashCode(raw.getRaw());
+ nums[idx++] = function.hashBytes(raw.getRaw());
+ }
+ nums[idx] = function.hashInt(command.getBuilder().hashCode());
+ return function.hashLongs(nums);
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+
+ private long maximumSize = DEFAULT_MAXIMUM_SIZE;
+ private long expireTime = DEFAULT_EXPIRE_SECONDS;
+ private final TimeUnit expireTimeUnit = TimeUnit.SECONDS;
+
+ private LongHashFunction hashFunction = DEFAULT_HASH_FUNCTION;
+
+ private Builder() { }
+
+ public Builder maximumSize(int size) {
+ this.maximumSize = size;
+ return this;
+ }
+
+ public Builder ttl(int seconds) {
+ this.expireTime = seconds;
+ return this;
+ }
+
+ public Builder hashFunction(LongHashFunction function) {
+ this.hashFunction = function;
+ return this;
+ }
+
+ public CaffeineCSC build() {
+ Caffeine cb = Caffeine.newBuilder();
+
+ cb.maximumSize(maximumSize);
+
+ cb.expireAfterWrite(expireTime, expireTimeUnit);
+
+ return new CaffeineCSC(cb.build(), hashFunction);
}
- return 31 * result + command.getBuilder().hashCode();
}
}
diff --git a/src/main/java/redis/clients/jedis/util/GuavaCSC.java b/src/main/java/redis/clients/jedis/util/GuavaCSC.java
index 282c03790e..643c62b9a9 100644
--- a/src/main/java/redis/clients/jedis/util/GuavaCSC.java
+++ b/src/main/java/redis/clients/jedis/util/GuavaCSC.java
@@ -4,7 +4,6 @@
import com.google.common.cache.CacheBuilder;
import com.google.common.hash.HashFunction;
import com.google.common.hash.Hasher;
-import java.time.Duration;
import java.util.concurrent.TimeUnit;
import redis.clients.jedis.ClientSideCache;
import redis.clients.jedis.CommandObject;
@@ -12,8 +11,8 @@
public class GuavaCSC extends ClientSideCache {
private static final int DEFAULT_MAXIMUM_SIZE = 10_000;
- private static final int DEFAULT_EXPIRE_MINUTES = 5;
- private static final HashFunction DEFAULT_FUNCTION = com.google.common.hash.Hashing.fingerprint2011();
+ private static final int DEFAULT_EXPIRE_SECONDS = 100;
+ private static final HashFunction DEFAULT_HASH_FUNCTION = com.google.common.hash.Hashing.fingerprint2011();
private final Cache cache;
private final HashFunction function;
@@ -58,11 +57,10 @@ public static Builder builder() {
public static class Builder {
private long maximumSize = DEFAULT_MAXIMUM_SIZE;
- private Duration expireDuration = null;
- private long expireTime = DEFAULT_EXPIRE_MINUTES;
- private TimeUnit expireTimeUnit = TimeUnit.MINUTES;
+ private long expireTime = DEFAULT_EXPIRE_SECONDS;
+ private final TimeUnit expireTimeUnit = TimeUnit.SECONDS;
- private HashFunction hashFunction = DEFAULT_FUNCTION;
+ private HashFunction hashFunction = DEFAULT_HASH_FUNCTION;
private Builder() { }
@@ -71,14 +69,8 @@ public Builder maximumSize(int size) {
return this;
}
- public Builder ttl(Duration duration) {
- this.expireDuration = duration;
- return this;
- }
-
- public Builder ttl(long time, TimeUnit unit) {
- this.expireTime = time;
- this.expireTimeUnit = unit;
+ public Builder ttl(int seconds) {
+ this.expireTime = seconds;
return this;
}
@@ -92,11 +84,7 @@ public GuavaCSC build() {
cb.maximumSize(maximumSize);
- if (expireDuration != null) {
- cb.expireAfterWrite(expireDuration);
- } else {
- cb.expireAfterWrite(expireTime, expireTimeUnit);
- }
+ cb.expireAfterWrite(expireTime, expireTimeUnit);
return new GuavaCSC(cb.build(), hashFunction);
}
From d3acff22529e6469bb371cc909feaf3752df59e2 Mon Sep 17 00:00:00 2001
From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com>
Date: Thu, 1 Feb 2024 15:02:39 +0600
Subject: [PATCH 10/16] Clean-up keyHashes map
---
.../redis/clients/jedis/ClientSideCache.java | 33 +++++++++----------
1 file changed, 15 insertions(+), 18 deletions(-)
diff --git a/src/main/java/redis/clients/jedis/ClientSideCache.java b/src/main/java/redis/clients/jedis/ClientSideCache.java
index 2b15fb75df..1371a2d376 100644
--- a/src/main/java/redis/clients/jedis/ClientSideCache.java
+++ b/src/main/java/redis/clients/jedis/ClientSideCache.java
@@ -1,23 +1,19 @@
package redis.clients.jedis;
import java.nio.ByteBuffer;
-import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Function;
import redis.clients.jedis.util.SafeEncoder;
public abstract class ClientSideCache {
- private final Map> keyHashes; // TODO: clean-up
- private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
- private final Lock readLock = rwl.readLock();
- private final Lock writeLock = rwl.writeLock();
+ private final Map> keyHashes;
+ private final ReentrantLock writeLock = new ReentrantLock();
protected ClientSideCache() {
this.keyHashes = new ConcurrentHashMap<>();
@@ -33,24 +29,25 @@ final void invalidate(List list) {
return;
}
- Set hashes = new HashSet<>();
- list.forEach(key -> hashes.addAll(getHashes(key)));
- invalidateAll(hashes);
- // TODO: clean-up keyHashes
+ list.forEach(this::invalidate0);
}
- private Set getHashes(Object key) {
+ private void invalidate0(Object key) {
if (!(key instanceof byte[])) {
throw new AssertionError("" + key.getClass().getSimpleName() + " is not supported. Value: " + String.valueOf(key));
}
final ByteBuffer mapKey = makeKey((byte[]) key);
- readLock.lock();
- try {
- Set hashes = keyHashes.get(mapKey);
- return hashes != null ? hashes : Collections.emptySet();
- } finally {
- readLock.unlock();
+
+ Set hashes = keyHashes.get(mapKey);
+ if (hashes != null) {
+ writeLock.lock();
+ try {
+ invalidateAll(hashes);
+ keyHashes.remove(mapKey);
+ } finally {
+ writeLock.unlock();
+ }
}
}
From ec395b5eef4a8107a54e4e86f864acc963754430 Mon Sep 17 00:00:00 2001
From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com>
Date: Sun, 4 Feb 2024 17:09:07 +0600
Subject: [PATCH 11/16] Support Client-side caching through URI/URL
---
.../java/redis/clients/jedis/JedisPooled.java | 4 +-
.../redis/clients/jedis/UnifiedJedis.java | 8 +-
.../clients/jedis/util/JedisURIHelper.java | 78 +++++++++++++++++--
3 files changed, 81 insertions(+), 9 deletions(-)
diff --git a/src/main/java/redis/clients/jedis/JedisPooled.java b/src/main/java/redis/clients/jedis/JedisPooled.java
index 44e476d7b8..a5840c6530 100644
--- a/src/main/java/redis/clients/jedis/JedisPooled.java
+++ b/src/main/java/redis/clients/jedis/JedisPooled.java
@@ -26,7 +26,7 @@ public JedisPooled() {
* @param url
*/
public JedisPooled(final String url) {
- this(URI.create(url));
+ super(url);
}
/**
@@ -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 factory) {
diff --git a/src/main/java/redis/clients/jedis/UnifiedJedis.java b/src/main/java/redis/clients/jedis/UnifiedJedis.java
index 3a2dec9d77..1bdd7a7ca8 100644
--- a/src/main/java/redis/clients/jedis/UnifiedJedis.java
+++ b/src/main/java/redis/clients/jedis/UnifiedJedis.java
@@ -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) {
@@ -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);
}
diff --git a/src/main/java/redis/clients/jedis/util/JedisURIHelper.java b/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
index 6bbd1599a8..8f0a245af6 100644
--- a/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
+++ b/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
@@ -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;
@@ -54,11 +55,11 @@ 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 ("protocol".equals(param.substring(0, idx))) {
+ String ver = param.substring(idx + 1);
for (RedisProtocol proto : RedisProtocol.values()) {
if (proto.version().equals(ver)) {
return proto;
@@ -70,6 +71,73 @@ 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("=");
+ 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":
+ maxSize = Integer.parseInt(val);
+ break;
+
+ case "ttl":
+ ttl = Integer.parseInt(val);
+ break;
+ }
+ }
+
+ // special cases
+ if (ZERO_INTEGER.equals(maxSize)) {
+ return null;
+ }
+ if (ZERO_INTEGER.equals(ttl)) {
+ ttl = null; // below, only null will be checked
+ }
+ if (!guava && !caffeine) {
+ throw new IllegalArgumentException("The cache library (guava OR caffeine) must be selected.");
+ }
+
+ 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;
From cb40a985b6c3d265e3999e78b23e80d11e3b67ca Mon Sep 17 00:00:00 2001
From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com>
Date: Wed, 7 Feb 2024 18:46:17 +0600
Subject: [PATCH 12/16] check idx of '=' sign
---
src/main/java/redis/clients/jedis/util/JedisURIHelper.java | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/main/java/redis/clients/jedis/util/JedisURIHelper.java b/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
index 8f0a245af6..b12cb0ea66 100644
--- a/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
+++ b/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
@@ -58,6 +58,7 @@ public static RedisProtocol getRedisProtocol(URI uri) {
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()) {
@@ -84,6 +85,8 @@ public static ClientSideCache getClientSideCache(URI uri) {
String[] params = uri.getQuery().split("&");
for (String param : params) {
int idx = param.indexOf("=");
+ if (idx < 0) continue;
+
String key = param.substring(0, idx);
String val = param.substring(idx + 1);
From 9aa8a130b703ffa36ad6b67bc7aaaaa236127762 Mon Sep 17 00:00:00 2001
From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com>
Date: Wed, 7 Feb 2024 18:47:17 +0600
Subject: [PATCH 13/16] nicer exception
---
.../redis/clients/jedis/util/JedisURIHelper.java | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/src/main/java/redis/clients/jedis/util/JedisURIHelper.java b/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
index b12cb0ea66..44f294d3dc 100644
--- a/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
+++ b/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
@@ -5,6 +5,7 @@
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Protocol;
import redis.clients.jedis.RedisProtocol;
+import redis.clients.jedis.exceptions.JedisValidationException;
public final class JedisURIHelper {
@@ -106,11 +107,19 @@ public static ClientSideCache getClientSideCache(URI uri) {
break;
case "cache_max_size":
- maxSize = Integer.parseInt(val);
+ try {
+ maxSize = Integer.parseInt(val);
+ } catch (NumberFormatException nfe) {
+ throw new JedisValidationException("Value of cache_max_size must be an integer.", nfe);
+ }
break;
case "ttl":
- ttl = Integer.parseInt(val);
+ try {
+ ttl = Integer.parseInt(val);
+ } catch (NumberFormatException nfe) {
+ throw new JedisValidationException("Value of ttl must be an integer denoting seconds.", nfe);
+ }
break;
}
}
From be3b45b7dfb8c47ff4e8b121c15b95fb2a0b5782 Mon Sep 17 00:00:00 2001
From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com>
Date: Wed, 7 Feb 2024 18:49:13 +0600
Subject: [PATCH 14/16] edit/fix condition
---
src/main/java/redis/clients/jedis/util/JedisURIHelper.java | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/main/java/redis/clients/jedis/util/JedisURIHelper.java b/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
index 44f294d3dc..e574c41227 100644
--- a/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
+++ b/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
@@ -128,12 +128,12 @@ public static ClientSideCache getClientSideCache(URI uri) {
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.");
+ }
if (ZERO_INTEGER.equals(ttl)) {
ttl = null; // below, only null will be checked
}
- if (!guava && !caffeine) {
- throw new IllegalArgumentException("The cache library (guava OR caffeine) must be selected.");
- }
if (guava) {
GuavaCSC.Builder guavaBuilder = GuavaCSC.builder();
From 1067fc3fa85c5e483e15c716da0da9fd6c138d1c Mon Sep 17 00:00:00 2001
From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com>
Date: Wed, 7 Feb 2024 18:53:47 +0600
Subject: [PATCH 15/16] rename param
---
src/main/java/redis/clients/jedis/util/JedisURIHelper.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/main/java/redis/clients/jedis/util/JedisURIHelper.java b/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
index e574c41227..65e4585bf0 100644
--- a/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
+++ b/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
@@ -114,11 +114,11 @@ public static ClientSideCache getClientSideCache(URI uri) {
}
break;
- case "ttl":
+ case "cache_ttl":
try {
ttl = Integer.parseInt(val);
} catch (NumberFormatException nfe) {
- throw new JedisValidationException("Value of ttl must be an integer denoting seconds.", nfe);
+ throw new JedisValidationException("Value of cache_ttl must be an integer denoting seconds.", nfe);
}
break;
}
From aa1012b094b6ae7624311309ecf8f36e87a8a28b Mon Sep 17 00:00:00 2001
From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com>
Date: Thu, 15 Feb 2024 15:46:30 +0600
Subject: [PATCH 16/16] Throw IllegalArgumentException at all such cases
---
src/main/java/redis/clients/jedis/util/JedisURIHelper.java | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/main/java/redis/clients/jedis/util/JedisURIHelper.java b/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
index 65e4585bf0..2d73cf04d4 100644
--- a/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
+++ b/src/main/java/redis/clients/jedis/util/JedisURIHelper.java
@@ -5,7 +5,6 @@
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Protocol;
import redis.clients.jedis.RedisProtocol;
-import redis.clients.jedis.exceptions.JedisValidationException;
public final class JedisURIHelper {
@@ -110,7 +109,7 @@ public static ClientSideCache getClientSideCache(URI uri) {
try {
maxSize = Integer.parseInt(val);
} catch (NumberFormatException nfe) {
- throw new JedisValidationException("Value of cache_max_size must be an integer.", nfe);
+ throw new IllegalArgumentException("Value of cache_max_size must be an integer.", nfe);
}
break;
@@ -118,7 +117,7 @@ public static ClientSideCache getClientSideCache(URI uri) {
try {
ttl = Integer.parseInt(val);
} catch (NumberFormatException nfe) {
- throw new JedisValidationException("Value of cache_ttl must be an integer denoting seconds.", nfe);
+ throw new IllegalArgumentException("Value of cache_ttl must be an integer denoting seconds.", nfe);
}
break;
}