From f27bb1c86d61c086b96d833f86ac8e2796afc6e1 Mon Sep 17 00:00:00 2001 From: atakavci Date: Wed, 14 Aug 2024 14:11:49 +0300 Subject: [PATCH 1/8] add cacheconfig --- .../java/redis/clients/jedis/JedisPooled.java | 17 ++- .../redis/clients/jedis/UnifiedJedis.java | 2 +- .../redis/clients/jedis/csc/CacheConfig.java | 69 +++++++++++ .../clients/jedis/csc/CacheProvider.java | 39 +++++++ .../jedis/csc/CaffeineClientSideCache.java | 7 ++ .../redis/clients/jedis/csc/DefaultCache.java | 8 +- .../clients/jedis/csc/EvictionPolicyType.java | 2 + .../jedis/csc/GuavaClientSideCache.java | 7 ++ .../jedis/benchmark/CSCPooleadBenchmark.java | 3 +- .../AllowAndDenyListClientSideCacheTest.java | 10 +- .../csc/CaffeineClientSideCacheTest.java | 17 ++- .../csc/ClientSideCacheFunctionalityTest.java | 14 +-- .../jedis/csc/GuavaClientSideCacheTest.java | 9 +- .../csc/JedisPooledClientSideCacheTest.java | 107 +++++++++--------- .../redis/clients/jedis/csc/TestCache.java | 8 +- .../clients/jedis/csc/TestJedisPooled.java | 21 ++++ 16 files changed, 249 insertions(+), 91 deletions(-) create mode 100644 src/main/java/redis/clients/jedis/csc/CacheConfig.java create mode 100644 src/main/java/redis/clients/jedis/csc/CacheProvider.java create mode 100644 src/main/java/redis/clients/jedis/csc/EvictionPolicyType.java create mode 100644 src/test/java/redis/clients/jedis/csc/TestJedisPooled.java diff --git a/src/main/java/redis/clients/jedis/JedisPooled.java b/src/main/java/redis/clients/jedis/JedisPooled.java index 498bcb02c8..f67915c1ec 100644 --- a/src/main/java/redis/clients/jedis/JedisPooled.java +++ b/src/main/java/redis/clients/jedis/JedisPooled.java @@ -9,6 +9,8 @@ import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import redis.clients.jedis.annots.Experimental; import redis.clients.jedis.csc.Cache; +import redis.clients.jedis.csc.CacheConfig; +import redis.clients.jedis.csc.CacheProvider; import redis.clients.jedis.providers.PooledConnectionProvider; import redis.clients.jedis.util.JedisURIHelper; import redis.clients.jedis.util.Pool; @@ -78,10 +80,15 @@ public JedisPooled(final HostAndPort hostAndPort, final JedisClientConfig client } @Experimental - public JedisPooled(final HostAndPort hostAndPort, final JedisClientConfig clientConfig, Cache clientSideCache) { + protected JedisPooled(final HostAndPort hostAndPort, final JedisClientConfig clientConfig, Cache clientSideCache) { super(hostAndPort, clientConfig, clientSideCache); } + @Experimental + public JedisPooled(final HostAndPort hostAndPort, final JedisClientConfig clientConfig, CacheConfig cacheConfig) { + this(hostAndPort, clientConfig, new CacheProvider().getCache(cacheConfig)); + } + public JedisPooled(PooledObjectFactory factory) { this(new PooledConnectionProvider(factory)); } @@ -383,12 +390,18 @@ public JedisPooled(final HostAndPort hostAndPort, final JedisClientConfig client } @Experimental - public JedisPooled(final HostAndPort hostAndPort, final JedisClientConfig clientConfig, Cache clientSideCache, + protected JedisPooled(final HostAndPort hostAndPort, final JedisClientConfig clientConfig, Cache clientSideCache, final GenericObjectPoolConfig poolConfig) { super(new PooledConnectionProvider(hostAndPort, clientConfig, clientSideCache, poolConfig), clientConfig.getRedisProtocol(), clientSideCache); } + @Experimental + public JedisPooled(final HostAndPort hostAndPort, final JedisClientConfig clientConfig, CacheConfig cacheConfig, + final GenericObjectPoolConfig poolConfig) { + this(hostAndPort, clientConfig, new CacheProvider().getCache(cacheConfig), poolConfig); + } + public JedisPooled(final GenericObjectPoolConfig poolConfig, final JedisSocketFactory jedisSocketFactory, final JedisClientConfig clientConfig) { super(new PooledConnectionProvider(new ConnectionFactory(jedisSocketFactory, clientConfig), poolConfig), diff --git a/src/main/java/redis/clients/jedis/UnifiedJedis.java b/src/main/java/redis/clients/jedis/UnifiedJedis.java index 405220b83e..c3c938cc5d 100644 --- a/src/main/java/redis/clients/jedis/UnifiedJedis.java +++ b/src/main/java/redis/clients/jedis/UnifiedJedis.java @@ -95,7 +95,7 @@ public UnifiedJedis(HostAndPort hostAndPort, JedisClientConfig clientConfig) { } @Experimental - public UnifiedJedis(HostAndPort hostAndPort, JedisClientConfig clientConfig, Cache clientSideCache) { + protected UnifiedJedis(HostAndPort hostAndPort, JedisClientConfig clientConfig, Cache clientSideCache) { this(new PooledConnectionProvider(hostAndPort, clientConfig, clientSideCache), clientConfig.getRedisProtocol(), clientSideCache); } diff --git a/src/main/java/redis/clients/jedis/csc/CacheConfig.java b/src/main/java/redis/clients/jedis/csc/CacheConfig.java new file mode 100644 index 0000000000..6af61aaf0d --- /dev/null +++ b/src/main/java/redis/clients/jedis/csc/CacheConfig.java @@ -0,0 +1,69 @@ +package redis.clients.jedis.csc; + +public class CacheConfig { + + public enum EvictionPolicyType { + DEFAULT, LRU + } + + public enum CacheType { + DEFAULT, GUAVA, CAFFEINE + } + + private int maxSize; + private EvictionPolicyType evictionPolicyType; + private ClientSideCacheable cacheable; + private CacheType cacheType; + + public int getMaxSize() { + return maxSize; + } + + public CacheType getCacheType() { + return cacheType; + } + + public EvictionPolicyType getEvictionPolicyType() { + return evictionPolicyType; + } + + public ClientSideCacheable getCacheable() { + return cacheable; + } + + public static class Builder { + private int maxSize; + private EvictionPolicyType evictionPolicyType = EvictionPolicyType.DEFAULT; + private ClientSideCacheable cacheable = DefaultClientSideCacheable.INSTANCE; + private CacheType cacheType; + + public Builder maxSize(int maxSize) { + this.maxSize = maxSize; + return this; + } + + public Builder cacheType(CacheType cacheType) { + this.cacheType = cacheType; + return this; + } + + public Builder evictionPolicyType(EvictionPolicyType evictionPolicyType) { + this.evictionPolicyType = evictionPolicyType; + return this; + } + + public Builder cacheable(ClientSideCacheable cacheable) { + this.cacheable = cacheable; + return this; + } + + public CacheConfig build() { + CacheConfig cacheConfig = new CacheConfig(); + cacheConfig.maxSize = this.maxSize; + cacheConfig.evictionPolicyType = this.evictionPolicyType; + cacheConfig.cacheable = this.cacheable; + cacheConfig.cacheType = this.cacheType; + return cacheConfig; + } + } +} \ No newline at end of file diff --git a/src/main/java/redis/clients/jedis/csc/CacheProvider.java b/src/main/java/redis/clients/jedis/csc/CacheProvider.java new file mode 100644 index 0000000000..b04cb781aa --- /dev/null +++ b/src/main/java/redis/clients/jedis/csc/CacheProvider.java @@ -0,0 +1,39 @@ +package redis.clients.jedis.csc; + +import java.util.HashMap; + +import redis.clients.jedis.csc.CacheConfig.EvictionPolicyType; + +public class CacheProvider { + + public Cache getCache(CacheConfig config) { + switch (config.getEvictionPolicyType()) { + case LRU: + return new DefaultCache(config.getMaxSize(), new HashMap(), config.getCacheable(), + new LRUEviction(0)); + default: + return new DefaultCache(config.getMaxSize(), config.getCacheable()); + } + } + + public Cache getCache(CacheConfig config, HashMap map) { + switch (config.getCacheType()) { + case GUAVA: + return new GuavaClientSideCache(config.getMaxSize(), config.getCacheable(), + getEvictionPolicy(config.getEvictionPolicyType(), config.getMaxSize())); + case CAFFEINE: + return new CaffeineClientSideCache(config.getMaxSize(), config.getCacheable(), + getEvictionPolicy(config.getEvictionPolicyType(), config.getMaxSize())); + default: + return new DefaultCache(config.getMaxSize(), map, config.getCacheable(), + getEvictionPolicy(config.getEvictionPolicyType(), config.getMaxSize())); + } + } + + private EvictionPolicy getEvictionPolicy(EvictionPolicyType evictionPolicyType, int initialCapacity) { + switch (evictionPolicyType) { + default: + return new LRUEviction(initialCapacity); + } + } +} \ No newline at end of file diff --git a/src/main/java/redis/clients/jedis/csc/CaffeineClientSideCache.java b/src/main/java/redis/clients/jedis/csc/CaffeineClientSideCache.java index 85627dba29..0a8a8aa744 100644 --- a/src/main/java/redis/clients/jedis/csc/CaffeineClientSideCache.java +++ b/src/main/java/redis/clients/jedis/csc/CaffeineClientSideCache.java @@ -24,6 +24,13 @@ public CaffeineClientSideCache(int maximumSize, EvictionPolicy evictionPolicy) { this.evictionPolicy.setCache(this); } + public CaffeineClientSideCache(int maximumSize, ClientSideCacheable cacheable, EvictionPolicy evictionPolicy) { + super(maximumSize, cacheable); + this.cache = Caffeine.newBuilder().build(); + this.evictionPolicy = evictionPolicy; + this.evictionPolicy.setCache(this); + } + @Override protected final void clearStore() { cache.invalidateAll(); diff --git a/src/main/java/redis/clients/jedis/csc/DefaultCache.java b/src/main/java/redis/clients/jedis/csc/DefaultCache.java index a382dc7623..57e39bb03a 100644 --- a/src/main/java/redis/clients/jedis/csc/DefaultCache.java +++ b/src/main/java/redis/clients/jedis/csc/DefaultCache.java @@ -9,19 +9,19 @@ public class DefaultCache extends AbstractCache { protected final Map cache; private final EvictionPolicy evictionPolicy; - public DefaultCache(int maximumSize) { + protected DefaultCache(int maximumSize) { this(maximumSize, new HashMap()); } - public DefaultCache(int maximumSize, Map map) { + protected DefaultCache(int maximumSize, Map map) { this(maximumSize, map, DefaultClientSideCacheable.INSTANCE, new LRUEviction(maximumSize)); } - public DefaultCache(int maximumSize, ClientSideCacheable cacheable) { + protected DefaultCache(int maximumSize, ClientSideCacheable cacheable) { this(maximumSize, new HashMap(), cacheable, new LRUEviction(maximumSize)); } - public DefaultCache(int maximumSize, Map map, ClientSideCacheable cacheable, EvictionPolicy evictionPolicy) { + protected DefaultCache(int maximumSize, Map map, ClientSideCacheable cacheable, EvictionPolicy evictionPolicy) { super(maximumSize, cacheable); this.cache = map; this.evictionPolicy = evictionPolicy; diff --git a/src/main/java/redis/clients/jedis/csc/EvictionPolicyType.java b/src/main/java/redis/clients/jedis/csc/EvictionPolicyType.java new file mode 100644 index 0000000000..a8f454ce0a --- /dev/null +++ b/src/main/java/redis/clients/jedis/csc/EvictionPolicyType.java @@ -0,0 +1,2 @@ +package redis.clients.jedis.csc; + diff --git a/src/main/java/redis/clients/jedis/csc/GuavaClientSideCache.java b/src/main/java/redis/clients/jedis/csc/GuavaClientSideCache.java index 81853ad651..0d9ae16159 100644 --- a/src/main/java/redis/clients/jedis/csc/GuavaClientSideCache.java +++ b/src/main/java/redis/clients/jedis/csc/GuavaClientSideCache.java @@ -27,6 +27,13 @@ public GuavaClientSideCache(int maximumSize, EvictionPolicy evictionPolicy) { this.evictionPolicy.setCache(this); } + public GuavaClientSideCache(int maximumSize, ClientSideCacheable clientSideCacheable, EvictionPolicy evictionPolicy) { + super(maximumSize, clientSideCacheable); + this.cache = CacheBuilder.newBuilder().build(); + this.evictionPolicy = evictionPolicy; + this.evictionPolicy.setCache(this); + } + @Override public final void clearStore() { cache.invalidateAll(); diff --git a/src/test/java/redis/clients/jedis/benchmark/CSCPooleadBenchmark.java b/src/test/java/redis/clients/jedis/benchmark/CSCPooleadBenchmark.java index 8ee0580011..113ab659cd 100644 --- a/src/test/java/redis/clients/jedis/benchmark/CSCPooleadBenchmark.java +++ b/src/test/java/redis/clients/jedis/benchmark/CSCPooleadBenchmark.java @@ -7,6 +7,7 @@ import redis.clients.jedis.*; import redis.clients.jedis.csc.Cache; import redis.clients.jedis.csc.TestCache; +import redis.clients.jedis.csc.TestJedisPooled; public class CSCPooleadBenchmark { @@ -50,7 +51,7 @@ private static void withPool(Cache cache) throws Exception { .password(endpoint.getPassword()).build(); List tds = new ArrayList<>(); final AtomicInteger ind = new AtomicInteger(); - try (JedisPooled jedis = new JedisPooled(endpoint.getHostAndPort(), config, cache)) { + try (JedisPooled jedis = new TestJedisPooled(endpoint.getHostAndPort(), config, cache) ) { for (int i = 0; i < NUMBER_OF_THREADS; i++) { Thread hj = new Thread(new Runnable() { @Override diff --git a/src/test/java/redis/clients/jedis/csc/AllowAndDenyListClientSideCacheTest.java b/src/test/java/redis/clients/jedis/csc/AllowAndDenyListClientSideCacheTest.java index 83371c7f44..80db7a6ab0 100644 --- a/src/test/java/redis/clients/jedis/csc/AllowAndDenyListClientSideCacheTest.java +++ b/src/test/java/redis/clients/jedis/csc/AllowAndDenyListClientSideCacheTest.java @@ -23,7 +23,7 @@ private static Cache createTestCache(Map map, ClientSideCa @Test public void none() { HashMap map = new HashMap<>(); - try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), + try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), createTestCache(map, new AllowAndDenyListWithStringKeys(null, null, null, null)), singleConnectionPoolConfig.get())) { control.set("foo", "bar"); @@ -36,7 +36,7 @@ public void none() { @Test public void whiteListCommand() { HashMap map = new HashMap<>(); - try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), + try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), createTestCache(map, new AllowAndDenyListWithStringKeys(singleton(Protocol.Command.GET), null, null, null)), singleConnectionPoolConfig.get())) { control.set("foo", "bar"); @@ -49,7 +49,7 @@ public void whiteListCommand() { @Test public void blackListCommand() { HashMap map = new HashMap<>(); - try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), + try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), createTestCache(map, new AllowAndDenyListWithStringKeys(null, singleton(Protocol.Command.GET), null, null)), singleConnectionPoolConfig.get())) { control.set("foo", "bar"); @@ -62,7 +62,7 @@ public void blackListCommand() { @Test public void whiteListKey() { HashMap map = new HashMap<>(); - try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), + try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), createTestCache(map, new AllowAndDenyListWithStringKeys(null, null, singleton("foo"), null)), singleConnectionPoolConfig.get())) { control.set("foo", "bar"); @@ -75,7 +75,7 @@ public void whiteListKey() { @Test public void blackListKey() { HashMap map = new HashMap<>(); - try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), + try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), createTestCache(map, new AllowAndDenyListWithStringKeys(null, null, null, singleton("foo"))), singleConnectionPoolConfig.get())) { control.set("foo", "bar"); diff --git a/src/test/java/redis/clients/jedis/csc/CaffeineClientSideCacheTest.java b/src/test/java/redis/clients/jedis/csc/CaffeineClientSideCacheTest.java index 18a9b28d15..45f6dc0898 100644 --- a/src/test/java/redis/clients/jedis/csc/CaffeineClientSideCacheTest.java +++ b/src/test/java/redis/clients/jedis/csc/CaffeineClientSideCacheTest.java @@ -4,21 +4,17 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; -import com.github.benmanes.caffeine.cache.Cache; -import com.github.benmanes.caffeine.cache.Caffeine; -import com.github.benmanes.caffeine.cache.stats.CacheStats; - -import java.util.concurrent.TimeUnit; import org.hamcrest.Matchers; import org.junit.Test; import redis.clients.jedis.JedisPooled; +import redis.clients.jedis.csc.CacheConfig.CacheType; public class CaffeineClientSideCacheTest extends ClientSideCacheTestBase { @Test public void simple() { - CaffeineClientSideCache caffeine = new CaffeineClientSideCache(10); - try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), caffeine)) { + CacheConfig caffeineConfig = new CacheConfig.Builder().cacheType(CacheType.CAFFEINE).build(); + try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), caffeineConfig)) { control.set("foo", "bar"); assertEquals("bar", jedis.get("foo")); control.del("foo"); @@ -31,7 +27,8 @@ public void individualCommandsAndThenStats() { CaffeineClientSideCache caffeine = new CaffeineClientSideCache(100); - try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), caffeine, singleConnectionPoolConfig.get())) { + try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), caffeine, singleConnectionPoolConfig.get()) { + }) { control.set("foo", "bar"); assertEquals(0, caffeine.getSize()); assertEquals("bar", jedis.get("foo")); // cache miss @@ -56,7 +53,7 @@ public void maximumSizeExact() { control.set("k2", "v2"); CaffeineClientSideCache caffeine = new CaffeineClientSideCache(1); - try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), caffeine)) { + try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), caffeine)) { assertEquals(0, caffeine.getSize()); jedis.get("k1"); assertEquals(1, caffeine.getSize()); @@ -77,7 +74,7 @@ public void maximumSize() { } CaffeineClientSideCache caffeine = new CaffeineClientSideCache(maxSize); - try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), caffeine)) { + try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), caffeine)) { for (int i = 0; i < count; i++) { jedis.get("k" + i); assertThat(caffeine.getSize(), Matchers.lessThanOrEqualTo(maxEstimatedSize)); diff --git a/src/test/java/redis/clients/jedis/csc/ClientSideCacheFunctionalityTest.java b/src/test/java/redis/clients/jedis/csc/ClientSideCacheFunctionalityTest.java index 77e04c5e3b..5ab42ffedc 100644 --- a/src/test/java/redis/clients/jedis/csc/ClientSideCacheFunctionalityTest.java +++ b/src/test/java/redis/clients/jedis/csc/ClientSideCacheFunctionalityTest.java @@ -30,7 +30,7 @@ public void flushEntireCache() { HashMap map = new HashMap<>(); Cache clientSideCache = new TestCache(map); - JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), clientSideCache); + JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), clientSideCache); try { for (int i = 0; i < count; i++) { jedis.get("k" + i); @@ -54,7 +54,7 @@ public void removeSpecificKey() { // By using LinkedHashMap, we can get the hashes (map keys) at the same order of the actual keys. LinkedHashMap map = new LinkedHashMap<>(); Cache clientSideCache = new TestCache(map); - JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), clientSideCache); + JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), clientSideCache); try { for (int i = 0; i < count; i++) { jedis.get("k" + i); @@ -80,7 +80,7 @@ public void multiKeyOperation() { control.set("k2", "v2"); HashMap map = new HashMap<>(); - try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), new TestCache(map))) { + try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), new TestCache(map))) { jedis.mget("k1", "k2"); assertEquals(1, map.size()); } @@ -92,7 +92,7 @@ public void maximumSizeExact() { control.set("k2", "v2"); DefaultCache cache = new DefaultCache(1); - try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), cache)) { + try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), cache)) { assertEquals(0, cache.getSize()); jedis.get("k1"); assertEquals(1, cache.getSize()); @@ -107,7 +107,8 @@ public void maximumSizeExact() { public void testInvalidationWithUnifiedJedis() { Cache cache = new TestCache(); Cache mock = Mockito.spy(cache); - UnifiedJedis client = new UnifiedJedis(hnp, clientConfig.get(), mock); + UnifiedJedis client = new UnifiedJedis(hnp, clientConfig.get(), mock) { + }; UnifiedJedis controlClient = new UnifiedJedis(hnp, clientConfig.get()); try { @@ -123,7 +124,6 @@ public void testInvalidationWithUnifiedJedis() { //invalidating the cache and read it back from server Assert.assertEquals("bar2", client.get("foo")); - // ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(GuavaClientSideCache.class); Mockito.verify(mock, Mockito.times(1)).deleteByRedisKeys(Mockito.anyList()); Mockito.verify(mock, Mockito.times(2)).set(Mockito.any(CacheKey.class), Mockito.any(CacheEntry.class)); } finally { @@ -138,7 +138,7 @@ public void differentInstanceOnEachCacheHit() { TestCache testCache = new TestCache(map); // fill the cache for maxSize - try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), testCache)) { + try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), testCache)) { jedis.sadd("foo", "a"); jedis.sadd("foo", "b"); diff --git a/src/test/java/redis/clients/jedis/csc/GuavaClientSideCacheTest.java b/src/test/java/redis/clients/jedis/csc/GuavaClientSideCacheTest.java index fad64df8ab..689313c08c 100644 --- a/src/test/java/redis/clients/jedis/csc/GuavaClientSideCacheTest.java +++ b/src/test/java/redis/clients/jedis/csc/GuavaClientSideCacheTest.java @@ -4,7 +4,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; -import java.util.concurrent.TimeUnit; import org.hamcrest.Matchers; import org.junit.Test; import redis.clients.jedis.JedisPooled; @@ -14,7 +13,7 @@ public class GuavaClientSideCacheTest extends ClientSideCacheTestBase { @Test public void simple() { GuavaClientSideCache guava = new GuavaClientSideCache(10); - try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), guava)) { + try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), guava)) { control.set("foo", "bar"); assertEquals("bar", jedis.get("foo")); control.del("foo"); @@ -27,7 +26,7 @@ public void individualCommandsAndThenStats() { GuavaClientSideCache guava = new GuavaClientSideCache(10000); - try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), guava, + try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), guava, singleConnectionPoolConfig.get())) { control.set("foo", "bar"); assertEquals(0, guava.getSize()); @@ -53,7 +52,7 @@ public void maximumSizeExact() { control.set("k2", "v2"); GuavaClientSideCache guava = new GuavaClientSideCache(1); - try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), guava)) { + try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), guava)) { assertEquals(0, guava.getSize()); jedis.get("k1"); assertEquals(1, guava.getSize()); @@ -74,7 +73,7 @@ public void maximumSize() { } GuavaClientSideCache guava = new GuavaClientSideCache(maxSize); - try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), guava)) { + try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), guava)) { for (int i = 0; i < count; i++) { jedis.get("k" + i); assertThat(guava.getSize(), Matchers.lessThanOrEqualTo(maxEstimatedSize)); diff --git a/src/test/java/redis/clients/jedis/csc/JedisPooledClientSideCacheTest.java b/src/test/java/redis/clients/jedis/csc/JedisPooledClientSideCacheTest.java index de2e3e8144..0546beb149 100644 --- a/src/test/java/redis/clients/jedis/csc/JedisPooledClientSideCacheTest.java +++ b/src/test/java/redis/clients/jedis/csc/JedisPooledClientSideCacheTest.java @@ -107,7 +107,8 @@ private void sleep() { @Test public void simple() { - try (JedisPooled jedis = new JedisPooled(endpoint.getHostAndPort(), clientConfig.get(), new TestCache())) { + CacheConfig cacheConfig = new CacheConfig.Builder().maxSize(1000).build(); + try (JedisPooled jedis = new JedisPooled(endpoint.getHostAndPort(), clientConfig.get(), cacheConfig)) { control.set("foo", "bar"); assertEquals("bar", jedis.get("foo")); control.del("foo"); @@ -119,7 +120,7 @@ public void simple() { @Test public void simpleWithSimpleMap() { HashMap map = new HashMap<>(); - try (JedisPooled jedis = new JedisPooled(endpoint.getHostAndPort(), clientConfig.get(), new TestCache(map), + try (JedisPooled jedis = new TestJedisPooled(endpoint.getHostAndPort(), clientConfig.get(), new TestCache(map), singleConnectionPoolConfig.get())) { control.set("foo", "bar"); assertThat(map, Matchers.aMapWithSize(0)); @@ -140,7 +141,8 @@ public void simpleWithSimpleMap() { @Test public void flushAll() { - try (JedisPooled jedis = new JedisPooled(endpoint.getHostAndPort(), clientConfig.get(), new TestCache())) { + CacheConfig cacheConfig = new CacheConfig.Builder().maxSize(1000).build(); + try (JedisPooled jedis = new JedisPooled(endpoint.getHostAndPort(), clientConfig.get(), cacheConfig)) { control.set("foo", "bar"); assertEquals("bar", jedis.get("foo")); control.flushAll(); @@ -152,7 +154,7 @@ public void flushAll() { @Test public void flushAllWithSimpleMap() { HashMap map = new HashMap<>(); - try (JedisPooled jedis = new JedisPooled(endpoint.getHostAndPort(), clientConfig.get(), new TestCache(map), + try (JedisPooled jedis = new TestJedisPooled(endpoint.getHostAndPort(), clientConfig.get(), new TestCache(map), singleConnectionPoolConfig.get())) { control.set("foo", "bar"); assertThat(map, Matchers.aMapWithSize(0)); @@ -181,38 +183,37 @@ public void testSequentialAccess() throws InterruptedException { ReentrantLock lock = new ReentrantLock(true); ExecutorService executorService = Executors.newFixedThreadPool(threadCount); - // Create the shared mock instance of cache - TestCache testCache = new TestCache(); - - // Submit multiple threads to perform concurrent operations CountDownLatch latch = new CountDownLatch(threadCount); - for (int i = 0; i < threadCount; i++) { - executorService.submit(() -> { - try (JedisPooled jedis = new JedisPooled(endpoint.getHostAndPort(), clientConfig.get(), testCache)) { - for (int j = 0; j < iterations; j++) { - lock.lock(); - try { - // Simulate continious get and update operations and consume invalidation events meanwhile - assertEquals(control.get("foo"), jedis.get("foo")); - Integer value = new Integer(jedis.get("foo")); - assertEquals("OK", jedis.set("foo", (++value).toString())); - } finally { - lock.unlock(); + CacheConfig cacheConfig = new CacheConfig.Builder().maxSize(1000).build(); + try (JedisPooled jedis = new JedisPooled(endpoint.getHostAndPort(), clientConfig.get(), cacheConfig)) { + + // Submit multiple threads to perform concurrent operations + for (int i = 0; i < threadCount; i++) { + executorService.submit(() -> { + try { + for (int j = 0; j < iterations; j++) { + lock.lock(); + try { + // Simulate continious get and update operations and consume invalidation events meanwhile + assertEquals(control.get("foo"), jedis.get("foo")); + Integer value = new Integer(jedis.get("foo")); + assertEquals("OK", jedis.set("foo", (++value).toString())); + } finally { + lock.unlock(); + } } + } finally { + latch.countDown(); } - } finally { - latch.countDown(); - } - }); - } - - // wait for all threads to complete - latch.await(); - - // Verify the final value of "foo" in Redis - String finalValue = control.get("foo"); - assertEquals(threadCount * iterations, Integer.parseInt(finalValue)); + }); + } + // wait for all threads to complete + latch.await(); + // Verify the final value of "foo" in Redis + String finalValue = control.get("foo"); + assertEquals(threadCount * iterations, Integer.parseInt(finalValue)); + } } @Test @@ -231,26 +232,28 @@ public void testConcurrentAccessWithStats() throws InterruptedException { // Submit multiple threads to perform concurrent operations CountDownLatch latch = new CountDownLatch(threadCount); - for (int i = 0; i < threadCount; i++) { - executorService.submit(() -> { - try (JedisPooled jedis = new JedisPooled(endpoint.getHostAndPort(), clientConfig.get(), testCache)) { - for (int j = 0; j < iterations; j++) { - // Simulate continious get and update operations and consume invalidation events meanwhile - Integer value = new Integer(jedis.get("foo")) + 1; - assertEquals("OK", jedis.set("foo", value.toString())); + try (JedisPooled jedis = new TestJedisPooled(endpoint.getHostAndPort(), clientConfig.get(), testCache)) { + for (int i = 0; i < threadCount; i++) { + executorService.submit(() -> { + try { + for (int j = 0; j < iterations; j++) { + // Simulate continious get and update operations and consume invalidation events meanwhile + Integer value = new Integer(jedis.get("foo")) + 1; + assertEquals("OK", jedis.set("foo", value.toString())); + } + } finally { + latch.countDown(); } - } finally { - latch.countDown(); - } - }); - } + }); + } - // wait for all threads to complete - latch.await(); + // wait for all threads to complete + latch.await(); - CacheStats stats = testCache.getStats(); - assertEquals(threadCount * iterations, stats.getMissCount() + stats.getHitCount()); - assertEquals(stats.getMissCount(), stats.getLoadCount()); + CacheStats stats = testCache.getStats(); + assertEquals(threadCount * iterations, stats.getMissCount() + stats.getHitCount()); + assertEquals(stats.getMissCount(), stats.getLoadCount()); + } } @Test @@ -269,7 +272,7 @@ public void testMaxSize() throws InterruptedException { CountDownLatch latch = new CountDownLatch(threadCount); for (int i = 0; i < threadCount; i++) { executorService.submit(() -> { - try (JedisPooled jedis = new JedisPooled(endpoint.getHostAndPort(), clientConfig.get(), testCache)) { + try (JedisPooled jedis = new TestJedisPooled(endpoint.getHostAndPort(), clientConfig.get(), testCache)) { for (int j = 0; j < iterations; j++) { // Simulate continious get and update operations and consume invalidation events meanwhile assertEquals("OK", jedis.set("foo" + j, "foo" + j)); @@ -304,7 +307,7 @@ public void testEvictionPolicy() throws InterruptedException { TestCache testCache = new TestCache(maxSize, map, DefaultClientSideCacheable.INSTANCE); // fill the cache for maxSize - try (JedisPooled jedis = new JedisPooled(endpoint.getHostAndPort(), clientConfig.get(), testCache)) { + try (JedisPooled jedis = new TestJedisPooled(endpoint.getHostAndPort(), clientConfig.get(), testCache)) { for (int i = 0; i < maxSize; i++) { jedis.set("foo" + i, "bar" + i); assertEquals("bar" + i, jedis.get("foo" + i)); @@ -352,7 +355,7 @@ public void testEvictionPolicyMultithreaded() throws InterruptedException { TestCache cache = new TestCache(MAX_SIZE, new HashMap<>(), DefaultClientSideCacheable.INSTANCE); List tds = new ArrayList<>(); final AtomicInteger ind = new AtomicInteger(); - try (JedisPooled jedis = new JedisPooled(endpoint.getHostAndPort(), clientConfig.get(), cache)) { + try (JedisPooled jedis = new TestJedisPooled(endpoint.getHostAndPort(), clientConfig.get(), cache)) { for (int i = 0; i < NUMBER_OF_THREADS; i++) { Thread hj = new Thread(new Runnable() { @Override diff --git a/src/test/java/redis/clients/jedis/csc/TestCache.java b/src/test/java/redis/clients/jedis/csc/TestCache.java index fd90b1229b..8059514890 100644 --- a/src/test/java/redis/clients/jedis/csc/TestCache.java +++ b/src/test/java/redis/clients/jedis/csc/TestCache.java @@ -18,13 +18,13 @@ public TestCache(Map map, ClientSideCacheable cacheable) { super(10000, map, cacheable, new LRUEviction(10000)); } - public TestCache(int maxSize, Map map, ClientSideCacheable cacheable) { - this(maxSize, map, cacheable, new LRUEviction(maxSize)); + public TestCache(int maximumSize, Map map, ClientSideCacheable cacheable) { + this(maximumSize, map, cacheable, new LRUEviction(maximumSize)); } - public TestCache(int maxSize, Map map, ClientSideCacheable cacheable, + public TestCache(int maximumSize, Map map, ClientSideCacheable cacheable, EvictionPolicy evictionPolicy) { - super(maxSize, map, cacheable, evictionPolicy); + super(maximumSize, map, cacheable, evictionPolicy); } } diff --git a/src/test/java/redis/clients/jedis/csc/TestJedisPooled.java b/src/test/java/redis/clients/jedis/csc/TestJedisPooled.java new file mode 100644 index 0000000000..193d23fee0 --- /dev/null +++ b/src/test/java/redis/clients/jedis/csc/TestJedisPooled.java @@ -0,0 +1,21 @@ +package redis.clients.jedis.csc; + +import org.apache.commons.pool2.impl.GenericObjectPoolConfig; + +import redis.clients.jedis.Connection; +import redis.clients.jedis.HostAndPort; +import redis.clients.jedis.JedisClientConfig; +import redis.clients.jedis.JedisPooled; + +public class TestJedisPooled extends JedisPooled { + + public TestJedisPooled(final HostAndPort hostAndPort, final JedisClientConfig clientConfig, Cache clientSideCache) { + super(hostAndPort, clientConfig, clientSideCache); + } + + public TestJedisPooled(redis.clients.jedis.HostAndPort hnp, JedisClientConfig jedisClientConfig, + Cache guava, GenericObjectPoolConfig genericObjectPoolConfig) { + super(hnp, jedisClientConfig, guava, genericObjectPoolConfig); + } + +} From 2685c9b068c0ce73507261cdbe98741911259f51 Mon Sep 17 00:00:00 2001 From: atakavci Date: Wed, 14 Aug 2024 14:16:20 +0300 Subject: [PATCH 2/8] remove empty file --- src/main/java/redis/clients/jedis/csc/EvictionPolicyType.java | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 src/main/java/redis/clients/jedis/csc/EvictionPolicyType.java diff --git a/src/main/java/redis/clients/jedis/csc/EvictionPolicyType.java b/src/main/java/redis/clients/jedis/csc/EvictionPolicyType.java deleted file mode 100644 index a8f454ce0a..0000000000 --- a/src/main/java/redis/clients/jedis/csc/EvictionPolicyType.java +++ /dev/null @@ -1,2 +0,0 @@ -package redis.clients.jedis.csc; - From 0a828b3dcfdeb58ee633d1012add711fabc40a22 Mon Sep 17 00:00:00 2001 From: atakavci Date: Mon, 26 Aug 2024 17:20:12 +0300 Subject: [PATCH 3/8] -modify constructors with cache as public - trim guava caffeine --- pom.xml | 13 --- .../redis/clients/jedis/JedisCluster.java | 10 ++- .../java/redis/clients/jedis/JedisPooled.java | 4 +- .../redis/clients/jedis/JedisSentineled.java | 9 ++ .../redis/clients/jedis/UnifiedJedis.java | 2 +- .../redis/clients/jedis/csc/CacheConfig.java | 2 +- .../clients/jedis/csc/CacheProvider.java | 6 -- .../jedis/csc/CaffeineClientSideCache.java | 78 ----------------- .../jedis/csc/GuavaClientSideCache.java | 87 ------------------- .../jedis/benchmark/CSCPooleadBenchmark.java | 3 +- .../csc/AllowAndDenyListCacheableTest.java | 10 +-- .../csc/CaffeineClientSideCacheTest.java | 86 ------------------ .../csc/ClientSideCacheFunctionalityTest.java | 31 ++++--- .../jedis/csc/GuavaClientSideCacheTest.java | 85 ------------------ .../csc/JedisClusterClientSideCacheTest.java | 2 +- .../JedisPooledClientSideCacheTestBase.java | 2 +- .../JedisSentineledClientSideCacheTest.java | 2 +- .../clients/jedis/csc/TestJedisPooled.java | 21 ----- 18 files changed, 46 insertions(+), 407 deletions(-) delete mode 100644 src/main/java/redis/clients/jedis/csc/CaffeineClientSideCache.java delete mode 100644 src/main/java/redis/clients/jedis/csc/GuavaClientSideCache.java delete mode 100644 src/test/java/redis/clients/jedis/csc/CaffeineClientSideCacheTest.java delete mode 100644 src/test/java/redis/clients/jedis/csc/GuavaClientSideCacheTest.java delete mode 100644 src/test/java/redis/clients/jedis/csc/TestJedisPooled.java diff --git a/pom.xml b/pom.xml index b68329625f..8603699184 100644 --- a/pom.xml +++ b/pom.xml @@ -76,19 +76,6 @@ - - - com.google.guava - guava - 33.2.1-jre - true - - - com.github.ben-manes.caffeine - caffeine - 2.9.3 - true - diff --git a/src/main/java/redis/clients/jedis/JedisCluster.java b/src/main/java/redis/clients/jedis/JedisCluster.java index 423b1682cb..4988b5ee2f 100644 --- a/src/main/java/redis/clients/jedis/JedisCluster.java +++ b/src/main/java/redis/clients/jedis/JedisCluster.java @@ -11,6 +11,8 @@ import redis.clients.jedis.executors.ClusterCommandExecutor; import redis.clients.jedis.providers.ClusterConnectionProvider; import redis.clients.jedis.csc.Cache; +import redis.clients.jedis.csc.CacheConfig; +import redis.clients.jedis.csc.CacheProvider; import redis.clients.jedis.util.JedisClusterCRC16; public class JedisCluster extends UnifiedJedis { @@ -225,10 +227,16 @@ public JedisCluster(Set clusterNodes, JedisClientConfig clientConfi Duration.ofMillis(DEFAULT_MAX_ATTEMPTS * clientConfig.getSocketTimeoutMillis())); } + @Experimental + public JedisCluster(Set hnp, JedisClientConfig jedisClientConfig, CacheConfig cacheConfig) { + this(hnp, jedisClientConfig, new CacheProvider().getCache(cacheConfig)); + } + @Experimental public JedisCluster(Set clusterNodes, JedisClientConfig clientConfig, Cache clientSideCache, int maxAttempts, Duration maxTotalRetriesDuration) { - this(new ClusterConnectionProvider(clusterNodes, clientConfig, clientSideCache), maxAttempts, maxTotalRetriesDuration, + this(new ClusterConnectionProvider(clusterNodes, clientConfig, clientSideCache), maxAttempts, + maxTotalRetriesDuration, clientConfig.getRedisProtocol(), clientSideCache); } diff --git a/src/main/java/redis/clients/jedis/JedisPooled.java b/src/main/java/redis/clients/jedis/JedisPooled.java index f67915c1ec..7eb67374ae 100644 --- a/src/main/java/redis/clients/jedis/JedisPooled.java +++ b/src/main/java/redis/clients/jedis/JedisPooled.java @@ -80,7 +80,7 @@ public JedisPooled(final HostAndPort hostAndPort, final JedisClientConfig client } @Experimental - protected JedisPooled(final HostAndPort hostAndPort, final JedisClientConfig clientConfig, Cache clientSideCache) { + public JedisPooled(final HostAndPort hostAndPort, final JedisClientConfig clientConfig, Cache clientSideCache) { super(hostAndPort, clientConfig, clientSideCache); } @@ -390,7 +390,7 @@ public JedisPooled(final HostAndPort hostAndPort, final JedisClientConfig client } @Experimental - protected JedisPooled(final HostAndPort hostAndPort, final JedisClientConfig clientConfig, Cache clientSideCache, + public JedisPooled(final HostAndPort hostAndPort, final JedisClientConfig clientConfig, Cache clientSideCache, final GenericObjectPoolConfig poolConfig) { super(new PooledConnectionProvider(hostAndPort, clientConfig, clientSideCache, poolConfig), clientConfig.getRedisProtocol(), clientSideCache); diff --git a/src/main/java/redis/clients/jedis/JedisSentineled.java b/src/main/java/redis/clients/jedis/JedisSentineled.java index 35585f713f..da9eba4baf 100644 --- a/src/main/java/redis/clients/jedis/JedisSentineled.java +++ b/src/main/java/redis/clients/jedis/JedisSentineled.java @@ -4,6 +4,8 @@ import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import redis.clients.jedis.annots.Experimental; import redis.clients.jedis.csc.Cache; +import redis.clients.jedis.csc.CacheConfig; +import redis.clients.jedis.csc.CacheProvider; import redis.clients.jedis.providers.SentineledConnectionProvider; public class JedisSentineled extends UnifiedJedis { @@ -21,6 +23,13 @@ public JedisSentineled(String masterName, final JedisClientConfig masterClientCo sentinels, sentinelClientConfig), masterClientConfig.getRedisProtocol(), clientSideCache); } + @Experimental + public JedisSentineled(String masterName, final JedisClientConfig masterClientConfig, CacheConfig cacheConfig, + Set sentinels, final JedisClientConfig sentinelClientConfig) { + this(masterName, masterClientConfig, new CacheProvider().getCache(cacheConfig), + sentinels, sentinelClientConfig); + } + public JedisSentineled(String masterName, final JedisClientConfig masterClientConfig, final GenericObjectPoolConfig poolConfig, Set sentinels, final JedisClientConfig sentinelClientConfig) { diff --git a/src/main/java/redis/clients/jedis/UnifiedJedis.java b/src/main/java/redis/clients/jedis/UnifiedJedis.java index f3b3a888a3..e9b01d1426 100644 --- a/src/main/java/redis/clients/jedis/UnifiedJedis.java +++ b/src/main/java/redis/clients/jedis/UnifiedJedis.java @@ -95,7 +95,7 @@ public UnifiedJedis(HostAndPort hostAndPort, JedisClientConfig clientConfig) { } @Experimental - protected UnifiedJedis(HostAndPort hostAndPort, JedisClientConfig clientConfig, Cache clientSideCache) { + public UnifiedJedis(HostAndPort hostAndPort, JedisClientConfig clientConfig, Cache clientSideCache) { this(new PooledConnectionProvider(hostAndPort, clientConfig, clientSideCache), clientConfig.getRedisProtocol(), clientSideCache); } diff --git a/src/main/java/redis/clients/jedis/csc/CacheConfig.java b/src/main/java/redis/clients/jedis/csc/CacheConfig.java index fc75ef8159..99f9842b25 100644 --- a/src/main/java/redis/clients/jedis/csc/CacheConfig.java +++ b/src/main/java/redis/clients/jedis/csc/CacheConfig.java @@ -7,7 +7,7 @@ public enum EvictionPolicyType { } public enum CacheType { - DEFAULT, GUAVA, CAFFEINE + DEFAULT, } private int maxSize; diff --git a/src/main/java/redis/clients/jedis/csc/CacheProvider.java b/src/main/java/redis/clients/jedis/csc/CacheProvider.java index b04cb781aa..06f59ec6b3 100644 --- a/src/main/java/redis/clients/jedis/csc/CacheProvider.java +++ b/src/main/java/redis/clients/jedis/csc/CacheProvider.java @@ -18,12 +18,6 @@ public Cache getCache(CacheConfig config) { public Cache getCache(CacheConfig config, HashMap map) { switch (config.getCacheType()) { - case GUAVA: - return new GuavaClientSideCache(config.getMaxSize(), config.getCacheable(), - getEvictionPolicy(config.getEvictionPolicyType(), config.getMaxSize())); - case CAFFEINE: - return new CaffeineClientSideCache(config.getMaxSize(), config.getCacheable(), - getEvictionPolicy(config.getEvictionPolicyType(), config.getMaxSize())); default: return new DefaultCache(config.getMaxSize(), map, config.getCacheable(), getEvictionPolicy(config.getEvictionPolicyType(), config.getMaxSize())); diff --git a/src/main/java/redis/clients/jedis/csc/CaffeineClientSideCache.java b/src/main/java/redis/clients/jedis/csc/CaffeineClientSideCache.java deleted file mode 100644 index afacf843d7..0000000000 --- a/src/main/java/redis/clients/jedis/csc/CaffeineClientSideCache.java +++ /dev/null @@ -1,78 +0,0 @@ -package redis.clients.jedis.csc; - -import com.github.benmanes.caffeine.cache.Cache; -import com.github.benmanes.caffeine.cache.Caffeine; - -import redis.clients.jedis.annots.Experimental; - -import java.util.Collection; - -@Experimental -public class CaffeineClientSideCache extends AbstractCache { - - private final Cache cache; - private final EvictionPolicy evictionPolicy; - - public CaffeineClientSideCache(int maximumSize) { - this(maximumSize, new LRUEviction(maximumSize)); - } - - public CaffeineClientSideCache(int maximumSize, EvictionPolicy evictionPolicy) { - super(maximumSize); - this.cache = Caffeine.newBuilder().build(); - this.evictionPolicy = evictionPolicy; - this.evictionPolicy.setCache(this); - } - - public CaffeineClientSideCache(int maximumSize, Cacheable cacheable, EvictionPolicy evictionPolicy) { - super(maximumSize, cacheable); - this.cache = Caffeine.newBuilder().build(); - this.evictionPolicy = evictionPolicy; - this.evictionPolicy.setCache(this); - } - - @Override - protected final void clearStore() { - cache.invalidateAll(); - } - - @Override - public CacheEntry putIntoStore(CacheKey key, CacheEntry entry) { - cache.put(key, entry); - return entry; - } - - @Override - public CacheEntry getFromStore(CacheKey key) { - return cache.getIfPresent(key); - } - - // TODO: we should discuss if/how we utilize Caffeine and get back to here ! - - @Override - public int getSize() { - return (int) cache.estimatedSize(); - } - - @Override - public Collection getCacheEntries() { - throw new UnsupportedOperationException("Unimplemented method 'getCacheEntries'"); - } - - @Override - public EvictionPolicy getEvictionPolicy() { - return this.evictionPolicy; - } - - @Override - protected boolean removeFromStore(CacheKey cacheKey) { - cache.invalidate(cacheKey); - return true; - } - - @Override - protected boolean containsKeyInStore(CacheKey cacheKey) { - return cache.getIfPresent(cacheKey) != null; - } - -} diff --git a/src/main/java/redis/clients/jedis/csc/GuavaClientSideCache.java b/src/main/java/redis/clients/jedis/csc/GuavaClientSideCache.java deleted file mode 100644 index 3857e5bbf2..0000000000 --- a/src/main/java/redis/clients/jedis/csc/GuavaClientSideCache.java +++ /dev/null @@ -1,87 +0,0 @@ -package redis.clients.jedis.csc; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; - -import redis.clients.jedis.annots.Experimental; - -import java.util.Collection; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; - -@Experimental -public class GuavaClientSideCache extends AbstractCache { - - private final Cache cache; - private final EvictionPolicy evictionPolicy; - - public GuavaClientSideCache(int maximumSize) { - this(maximumSize, new LRUEviction(maximumSize)); - } - - public GuavaClientSideCache(int maximumSize, EvictionPolicy evictionPolicy) { - super(maximumSize); - this.cache = CacheBuilder.newBuilder().build(); - this.evictionPolicy = evictionPolicy; - this.evictionPolicy.setCache(this); - } - - public GuavaClientSideCache(int maximumSize, Cacheable clientSideCacheable, EvictionPolicy evictionPolicy) { - super(maximumSize, clientSideCacheable); - this.cache = CacheBuilder.newBuilder().build(); - this.evictionPolicy = evictionPolicy; - this.evictionPolicy.setCache(this); - } - - @Override - public final void clearStore() { - cache.invalidateAll(); - } - - public List remove(Iterable> keys) { - cache.invalidateAll(keys); - return StreamSupport.stream(keys.spliterator(), false) - .collect(Collectors.toList()); - } - - @Override - public CacheEntry putIntoStore(CacheKey key, CacheEntry entry) { - cache.put(key, entry); - return entry; - } - - @Override - public CacheEntry getFromStore(CacheKey key) { - return cache.getIfPresent(key); - } - - // TODO: we should discuss if/how we utilize Guava and get back to here ! - - @Override - public int getSize() { - return (int) cache.size(); - } - - @Override - public Collection getCacheEntries() { - throw new UnsupportedOperationException("Unimplemented method 'getCacheEntries'"); - } - - @Override - public EvictionPolicy getEvictionPolicy() { - return this.evictionPolicy; - } - - @Override - protected boolean removeFromStore(CacheKey cacheKey) { - cache.invalidate(cacheKey); - return true; - } - - @Override - protected boolean containsKeyInStore(CacheKey cacheKey) { - return cache.getIfPresent(cacheKey) != null; - } - -} diff --git a/src/test/java/redis/clients/jedis/benchmark/CSCPooleadBenchmark.java b/src/test/java/redis/clients/jedis/benchmark/CSCPooleadBenchmark.java index 113ab659cd..8ee0580011 100644 --- a/src/test/java/redis/clients/jedis/benchmark/CSCPooleadBenchmark.java +++ b/src/test/java/redis/clients/jedis/benchmark/CSCPooleadBenchmark.java @@ -7,7 +7,6 @@ import redis.clients.jedis.*; import redis.clients.jedis.csc.Cache; import redis.clients.jedis.csc.TestCache; -import redis.clients.jedis.csc.TestJedisPooled; public class CSCPooleadBenchmark { @@ -51,7 +50,7 @@ private static void withPool(Cache cache) throws Exception { .password(endpoint.getPassword()).build(); List tds = new ArrayList<>(); final AtomicInteger ind = new AtomicInteger(); - try (JedisPooled jedis = new TestJedisPooled(endpoint.getHostAndPort(), config, cache) ) { + try (JedisPooled jedis = new JedisPooled(endpoint.getHostAndPort(), config, cache)) { for (int i = 0; i < NUMBER_OF_THREADS; i++) { Thread hj = new Thread(new Runnable() { @Override diff --git a/src/test/java/redis/clients/jedis/csc/AllowAndDenyListCacheableTest.java b/src/test/java/redis/clients/jedis/csc/AllowAndDenyListCacheableTest.java index 8fd6299413..c8d311865c 100644 --- a/src/test/java/redis/clients/jedis/csc/AllowAndDenyListCacheableTest.java +++ b/src/test/java/redis/clients/jedis/csc/AllowAndDenyListCacheableTest.java @@ -23,7 +23,7 @@ private static Cache createTestCache(Map map, Cacheable ca @Test public void none() { HashMap map = new HashMap<>(); - try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), + try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), createTestCache(map, new AllowAndDenyListWithStringKeys(null, null, null, null)), singleConnectionPoolConfig.get())) { control.set("foo", "bar"); @@ -36,7 +36,7 @@ public void none() { @Test public void whiteListCommand() { HashMap map = new HashMap<>(); - try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), + try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), createTestCache(map, new AllowAndDenyListWithStringKeys(singleton(Protocol.Command.GET), null, null, null)), singleConnectionPoolConfig.get())) { control.set("foo", "bar"); @@ -49,7 +49,7 @@ public void whiteListCommand() { @Test public void blackListCommand() { HashMap map = new HashMap<>(); - try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), + try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), createTestCache(map, new AllowAndDenyListWithStringKeys(null, singleton(Protocol.Command.GET), null, null)), singleConnectionPoolConfig.get())) { control.set("foo", "bar"); @@ -62,7 +62,7 @@ public void blackListCommand() { @Test public void whiteListKey() { HashMap map = new HashMap<>(); - try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), + try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), createTestCache(map, new AllowAndDenyListWithStringKeys(null, null, singleton("foo"), null)), singleConnectionPoolConfig.get())) { control.set("foo", "bar"); @@ -75,7 +75,7 @@ public void whiteListKey() { @Test public void blackListKey() { HashMap map = new HashMap<>(); - try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), + try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), createTestCache(map, new AllowAndDenyListWithStringKeys(null, null, null, singleton("foo"))), singleConnectionPoolConfig.get())) { control.set("foo", "bar"); diff --git a/src/test/java/redis/clients/jedis/csc/CaffeineClientSideCacheTest.java b/src/test/java/redis/clients/jedis/csc/CaffeineClientSideCacheTest.java deleted file mode 100644 index 45f6dc0898..0000000000 --- a/src/test/java/redis/clients/jedis/csc/CaffeineClientSideCacheTest.java +++ /dev/null @@ -1,86 +0,0 @@ -package redis.clients.jedis.csc; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -import org.hamcrest.Matchers; -import org.junit.Test; -import redis.clients.jedis.JedisPooled; -import redis.clients.jedis.csc.CacheConfig.CacheType; - -public class CaffeineClientSideCacheTest extends ClientSideCacheTestBase { - - @Test - public void simple() { - CacheConfig caffeineConfig = new CacheConfig.Builder().cacheType(CacheType.CAFFEINE).build(); - try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), caffeineConfig)) { - control.set("foo", "bar"); - assertEquals("bar", jedis.get("foo")); - control.del("foo"); - assertEquals(null, jedis.get("foo")); - } - } - - @Test - public void individualCommandsAndThenStats() { - - CaffeineClientSideCache caffeine = new CaffeineClientSideCache(100); - - try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), caffeine, singleConnectionPoolConfig.get()) { - }) { - control.set("foo", "bar"); - assertEquals(0, caffeine.getSize()); - assertEquals("bar", jedis.get("foo")); // cache miss - assertEquals(1, caffeine.getSize()); - control.flushAll(); - assertEquals(1, caffeine.getSize()); - assertEquals(null, jedis.get("foo")); // cache miss - assertEquals(0, caffeine.getSize()); - jedis.ping(); - assertEquals(0, caffeine.getSize()); - assertNull(jedis.get("foo")); // cache miss - assertEquals(0, caffeine.getSize()); - } - - assertEquals(0, caffeine.getStats().getHitCount()); - assertEquals(caffeine.getStats().getMissCount(), 3); - } - - @Test - public void maximumSizeExact() { - control.set("k1", "v1"); - control.set("k2", "v2"); - - CaffeineClientSideCache caffeine = new CaffeineClientSideCache(1); - try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), caffeine)) { - assertEquals(0, caffeine.getSize()); - jedis.get("k1"); - assertEquals(1, caffeine.getSize()); - assertEquals(0, caffeine.getStats().getEvictCount()); - jedis.get("k2"); - assertEquals(1, caffeine.getSize()); - assertEquals(1, caffeine.getStats().getEvictCount()); - } - } - - @Test - public void maximumSize() { - final int maxSize = 10; - final int maxEstimatedSize = 10; - int count = 1000; - for (int i = 0; i < count; i++) { - control.set("k" + i, "v" + i); - } - - CaffeineClientSideCache caffeine = new CaffeineClientSideCache(maxSize); - try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), caffeine)) { - for (int i = 0; i < count; i++) { - jedis.get("k" + i); - assertThat(caffeine.getSize(), Matchers.lessThanOrEqualTo(maxEstimatedSize)); - } - } - assertThat(caffeine.getStats().getEvictCount(), Matchers.greaterThanOrEqualTo((long) count - maxEstimatedSize)); - } - -} diff --git a/src/test/java/redis/clients/jedis/csc/ClientSideCacheFunctionalityTest.java b/src/test/java/redis/clients/jedis/csc/ClientSideCacheFunctionalityTest.java index 381b3beed7..6be42fcae7 100644 --- a/src/test/java/redis/clients/jedis/csc/ClientSideCacheFunctionalityTest.java +++ b/src/test/java/redis/clients/jedis/csc/ClientSideCacheFunctionalityTest.java @@ -42,7 +42,7 @@ public void flushAllTest() { } Cache cache = new TestCache(); - try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), cache)) { + try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), cache)) { for (int i = 0; i < count; i++) { jedis.get("k" + i); } @@ -65,7 +65,7 @@ public void lruEvictionTest() { Map map = new LinkedHashMap<>(count); Cache cache = new DefaultCache(count, map); - try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), cache)) { + try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), cache)) { // Retrieve the 100 keys in the same order for (int i = 0; i < count; i++) { @@ -91,7 +91,7 @@ public void lruEvictionTest() { @Test // T.5.2 public void deleteByKeyUsingMGetTest() { Cache clientSideCache = new TestCache(); - try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), clientSideCache)) { + try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), clientSideCache)) { jedis.set("1", "one"); jedis.set("2", "two"); @@ -113,7 +113,7 @@ public void deleteByKeyTest() { // By using LinkedHashMap, we can get the hashes (map keys) at the same order of the actual keys. LinkedHashMap map = new LinkedHashMap<>(); Cache clientSideCache = new TestCache(map); - try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), clientSideCache)) { + try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), clientSideCache)) { for (int i = 0; i < count; i++) { jedis.get("k" + i); } @@ -144,7 +144,7 @@ public void deleteByKeysTest() { // By using LinkedHashMap, we can get the hashes (map keys) at the same order of the actual keys. LinkedHashMap map = new LinkedHashMap<>(); Cache clientSideCache = new TestCache(map); - try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), clientSideCache)) { + try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), clientSideCache)) { for (int i = 0; i < count; i++) { jedis.get("k" + i); } @@ -169,7 +169,7 @@ public void deleteByEntryTest() { HashMap map = new HashMap<>(); Cache clientSideCache = new TestCache(map); - try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), clientSideCache)) { + try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), clientSideCache)) { for (int i = 0; i < count; i++) { jedis.get("k" + i); } @@ -195,7 +195,7 @@ public void deleteByEntriesTest() { HashMap map = new HashMap<>(); Cache clientSideCache = new TestCache(map); - try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), clientSideCache)) { + try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), clientSideCache)) { for (int i = 0; i < count; i++) { jedis.get("k" + i); } @@ -215,7 +215,7 @@ public void multiKeyOperation() { control.set("k2", "v2"); Cache cache = new TestCache(); - try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), cache)) { + try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), cache)) { jedis.mget("k1", "k2"); assertEquals(1, cache.getSize()); } @@ -227,7 +227,7 @@ public void maximumSizeExact() { control.set("k2", "v2"); DefaultCache cache = new DefaultCache(1); - try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), cache)) { + try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), cache)) { assertEquals(0, cache.getSize()); jedis.get("k1"); assertEquals(1, cache.getSize()); @@ -242,8 +242,7 @@ public void maximumSizeExact() { public void testInvalidationWithUnifiedJedis() { Cache cache = new TestCache(); Cache mock = Mockito.spy(cache); - UnifiedJedis client = new UnifiedJedis(hnp, clientConfig.get(), mock) { - }; + UnifiedJedis client = new UnifiedJedis(hnp, clientConfig.get(), mock); UnifiedJedis controlClient = new UnifiedJedis(hnp, clientConfig.get()); try { @@ -273,7 +272,7 @@ public void differentInstanceOnEachCacheHit() { TestCache testCache = new TestCache(map); // fill the cache for maxSize - try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), testCache)) { + try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), testCache)) { jedis.sadd("foo", "a"); jedis.sadd("foo", "b"); @@ -350,7 +349,7 @@ public void testConcurrentAccessWithStats() throws InterruptedException { // Create the shared mock instance of cache TestCache testCache = new TestCache(); - try (JedisPooled jedis = new TestJedisPooled(endpoint.getHostAndPort(), clientConfig.get(), testCache)) { + try (JedisPooled jedis = new JedisPooled(endpoint.getHostAndPort(), clientConfig.get(), testCache)) { // Submit multiple threads to perform concurrent operations CountDownLatch latch = new CountDownLatch(threadCount); for (int i = 0; i < threadCount; i++) { @@ -390,7 +389,7 @@ public void testMaxSize() throws InterruptedException { // Create the shared mock instance of cache TestCache testCache = new TestCache(maxSize, map, DefaultCacheable.INSTANCE); - try (JedisPooled jedis = new TestJedisPooled(endpoint.getHostAndPort(), clientConfig.get(), testCache)) { + try (JedisPooled jedis = new JedisPooled(endpoint.getHostAndPort(), clientConfig.get(), testCache)) { // Submit multiple threads to perform concurrent operations CountDownLatch latch = new CountDownLatch(threadCount); for (int i = 0; i < threadCount; i++) { @@ -431,7 +430,7 @@ public void testEvictionPolicy() throws InterruptedException { TestCache testCache = new TestCache(maxSize, map, DefaultCacheable.INSTANCE); // fill the cache for maxSize - try (JedisPooled jedis = new TestJedisPooled(endpoint.getHostAndPort(), clientConfig.get(), testCache)) { + try (JedisPooled jedis = new JedisPooled(endpoint.getHostAndPort(), clientConfig.get(), testCache)) { for (int i = 0; i < maxSize; i++) { jedis.set("foo" + i, "bar" + i); assertEquals("bar" + i, jedis.get("foo" + i)); @@ -479,7 +478,7 @@ public void testEvictionPolicyMultithreaded() throws InterruptedException { TestCache cache = new TestCache(MAX_SIZE, new HashMap<>(), DefaultCacheable.INSTANCE); List tds = new ArrayList<>(); final AtomicInteger ind = new AtomicInteger(); - try (JedisPooled jedis = new TestJedisPooled(endpoint.getHostAndPort(), clientConfig.get(), cache)) { + try (JedisPooled jedis = new JedisPooled(endpoint.getHostAndPort(), clientConfig.get(), cache)) { for (int i = 0; i < NUMBER_OF_THREADS; i++) { Thread hj = new Thread(new Runnable() { @Override diff --git a/src/test/java/redis/clients/jedis/csc/GuavaClientSideCacheTest.java b/src/test/java/redis/clients/jedis/csc/GuavaClientSideCacheTest.java deleted file mode 100644 index 689313c08c..0000000000 --- a/src/test/java/redis/clients/jedis/csc/GuavaClientSideCacheTest.java +++ /dev/null @@ -1,85 +0,0 @@ -package redis.clients.jedis.csc; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -import org.hamcrest.Matchers; -import org.junit.Test; -import redis.clients.jedis.JedisPooled; - -public class GuavaClientSideCacheTest extends ClientSideCacheTestBase { - - @Test - public void simple() { - GuavaClientSideCache guava = new GuavaClientSideCache(10); - try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), guava)) { - control.set("foo", "bar"); - assertEquals("bar", jedis.get("foo")); - control.del("foo"); - assertEquals(null, jedis.get("foo")); - } - } - - @Test - public void individualCommandsAndThenStats() { - - GuavaClientSideCache guava = new GuavaClientSideCache(10000); - - try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), guava, - singleConnectionPoolConfig.get())) { - control.set("foo", "bar"); - assertEquals(0, guava.getSize()); - assertEquals("bar", jedis.get("foo")); // cache miss - assertEquals(1, guava.getSize()); - control.flushAll(); - assertEquals(1, guava.getSize()); - assertEquals(null, jedis.get("foo")); // cache miss - assertEquals(0, guava.getSize()); - jedis.ping(); - assertEquals(0, guava.getSize()); - assertNull(jedis.get("foo")); // cache miss - assertEquals(0, guava.getSize()); - } - - assertEquals(0, guava.getStats().getHitCount()); - assertEquals(guava.getStats().getMissCount(), 3); - } - - @Test - public void maximumSizeExact() { - control.set("k1", "v1"); - control.set("k2", "v2"); - - GuavaClientSideCache guava = new GuavaClientSideCache(1); - try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), guava)) { - assertEquals(0, guava.getSize()); - jedis.get("k1"); - assertEquals(1, guava.getSize()); - assertEquals(0, guava.getStats().getEvictCount()); - jedis.get("k2"); - assertEquals(1, guava.getSize()); - assertEquals(1, guava.getStats().getEvictCount()); - } - } - - @Test - public void maximumSize() { - final int maxSize = 10; - final int maxEstimatedSize = 40; - int count = 1000; - for (int i = 0; i < count; i++) { - control.set("k" + i, "v" + i); - } - - GuavaClientSideCache guava = new GuavaClientSideCache(maxSize); - try (JedisPooled jedis = new TestJedisPooled(hnp, clientConfig.get(), guava)) { - for (int i = 0; i < count; i++) { - jedis.get("k" + i); - assertThat(guava.getSize(), Matchers.lessThanOrEqualTo(maxEstimatedSize)); - } - } - assertThat(guava.getStats().getEvictCount(), Matchers.greaterThan((long) count - maxEstimatedSize)); - } - -} diff --git a/src/test/java/redis/clients/jedis/csc/JedisClusterClientSideCacheTest.java b/src/test/java/redis/clients/jedis/csc/JedisClusterClientSideCacheTest.java index 6a9bc883fd..a5823dea56 100644 --- a/src/test/java/redis/clients/jedis/csc/JedisClusterClientSideCacheTest.java +++ b/src/test/java/redis/clients/jedis/csc/JedisClusterClientSideCacheTest.java @@ -40,7 +40,7 @@ protected JedisCluster createCachedJedis(Cache cache) { @Override protected JedisCluster createCachedJedis(CacheConfig cacheConfig) { - throw new UnsupportedOperationException("Not supported yet."); + return new JedisCluster(hnp, clientConfig.get(), cacheConfig); } } diff --git a/src/test/java/redis/clients/jedis/csc/JedisPooledClientSideCacheTestBase.java b/src/test/java/redis/clients/jedis/csc/JedisPooledClientSideCacheTestBase.java index db44c65c53..e86ef936af 100644 --- a/src/test/java/redis/clients/jedis/csc/JedisPooledClientSideCacheTestBase.java +++ b/src/test/java/redis/clients/jedis/csc/JedisPooledClientSideCacheTestBase.java @@ -22,7 +22,7 @@ protected JedisPooled createRegularJedis() { @Override protected JedisPooled createCachedJedis(Cache cache) { - return new TestJedisPooled(endpoint.getHostAndPort(), endpoint.getClientConfigBuilder().resp3().build(), cache); + return new JedisPooled(endpoint.getHostAndPort(), endpoint.getClientConfigBuilder().resp3().build(), cache); } @Override diff --git a/src/test/java/redis/clients/jedis/csc/JedisSentineledClientSideCacheTest.java b/src/test/java/redis/clients/jedis/csc/JedisSentineledClientSideCacheTest.java index 7f4276c495..e81ec6e90f 100644 --- a/src/test/java/redis/clients/jedis/csc/JedisSentineledClientSideCacheTest.java +++ b/src/test/java/redis/clients/jedis/csc/JedisSentineledClientSideCacheTest.java @@ -35,7 +35,7 @@ protected JedisSentineled createCachedJedis(Cache cache) { @Override protected JedisSentineled createCachedJedis(CacheConfig cacheConfig) { - throw new UnsupportedOperationException("Not supported yet."); + return new JedisSentineled(MASTER_NAME, masterClientConfig, cacheConfig, sentinels, sentinelClientConfig); } } diff --git a/src/test/java/redis/clients/jedis/csc/TestJedisPooled.java b/src/test/java/redis/clients/jedis/csc/TestJedisPooled.java deleted file mode 100644 index 193d23fee0..0000000000 --- a/src/test/java/redis/clients/jedis/csc/TestJedisPooled.java +++ /dev/null @@ -1,21 +0,0 @@ -package redis.clients.jedis.csc; - -import org.apache.commons.pool2.impl.GenericObjectPoolConfig; - -import redis.clients.jedis.Connection; -import redis.clients.jedis.HostAndPort; -import redis.clients.jedis.JedisClientConfig; -import redis.clients.jedis.JedisPooled; - -public class TestJedisPooled extends JedisPooled { - - public TestJedisPooled(final HostAndPort hostAndPort, final JedisClientConfig clientConfig, Cache clientSideCache) { - super(hostAndPort, clientConfig, clientSideCache); - } - - public TestJedisPooled(redis.clients.jedis.HostAndPort hnp, JedisClientConfig jedisClientConfig, - Cache guava, GenericObjectPoolConfig genericObjectPoolConfig) { - super(hnp, jedisClientConfig, guava, genericObjectPoolConfig); - } - -} From 58969841696f3840e842bc1118c081df8b17feb1 Mon Sep 17 00:00:00 2001 From: atakavci Date: Mon, 26 Aug 2024 17:25:58 +0300 Subject: [PATCH 4/8] remove cachetype --- .../java/redis/clients/jedis/csc/CacheConfig.java | 15 --------------- .../redis/clients/jedis/csc/CacheProvider.java | 7 ++----- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/src/main/java/redis/clients/jedis/csc/CacheConfig.java b/src/main/java/redis/clients/jedis/csc/CacheConfig.java index 99f9842b25..0c3ccffe46 100644 --- a/src/main/java/redis/clients/jedis/csc/CacheConfig.java +++ b/src/main/java/redis/clients/jedis/csc/CacheConfig.java @@ -6,22 +6,14 @@ public enum EvictionPolicyType { DEFAULT, LRU } - public enum CacheType { - DEFAULT, - } - private int maxSize; private EvictionPolicyType evictionPolicyType; private Cacheable cacheable; - private CacheType cacheType; public int getMaxSize() { return maxSize; } - public CacheType getCacheType() { - return cacheType; - } public EvictionPolicyType getEvictionPolicyType() { return evictionPolicyType; @@ -35,17 +27,11 @@ public static class Builder { private int maxSize; private EvictionPolicyType evictionPolicyType = EvictionPolicyType.DEFAULT; private Cacheable cacheable = DefaultCacheable.INSTANCE; - private CacheType cacheType; public Builder maxSize(int maxSize) { this.maxSize = maxSize; return this; } - - public Builder cacheType(CacheType cacheType) { - this.cacheType = cacheType; - return this; - } public Builder evictionPolicyType(EvictionPolicyType evictionPolicyType) { this.evictionPolicyType = evictionPolicyType; @@ -62,7 +48,6 @@ public CacheConfig build() { cacheConfig.maxSize = this.maxSize; cacheConfig.evictionPolicyType = this.evictionPolicyType; cacheConfig.cacheable = this.cacheable; - cacheConfig.cacheType = this.cacheType; return cacheConfig; } } diff --git a/src/main/java/redis/clients/jedis/csc/CacheProvider.java b/src/main/java/redis/clients/jedis/csc/CacheProvider.java index 06f59ec6b3..aa20ea989e 100644 --- a/src/main/java/redis/clients/jedis/csc/CacheProvider.java +++ b/src/main/java/redis/clients/jedis/csc/CacheProvider.java @@ -17,11 +17,8 @@ public Cache getCache(CacheConfig config) { } public Cache getCache(CacheConfig config, HashMap map) { - switch (config.getCacheType()) { - default: - return new DefaultCache(config.getMaxSize(), map, config.getCacheable(), - getEvictionPolicy(config.getEvictionPolicyType(), config.getMaxSize())); - } + return new DefaultCache(config.getMaxSize(), map, config.getCacheable(), + getEvictionPolicy(config.getEvictionPolicyType(), config.getMaxSize())); } private EvictionPolicy getEvictionPolicy(EvictionPolicyType evictionPolicyType, int initialCapacity) { From b0478810da07353849d8f93d18eb390c6a6157ce Mon Sep 17 00:00:00 2001 From: atakavci Date: Tue, 27 Aug 2024 10:14:33 +0300 Subject: [PATCH 5/8] - add getCache to UnifiedJedis - add builder method to CacheConfig --- .../redis/clients/jedis/UnifiedJedis.java | 31 +++++++++++------ .../redis/clients/jedis/csc/CacheConfig.java | 5 ++- .../clients/jedis/csc/CacheConnection.java | 34 +++++++++++-------- .../csc/ClientSideCacheFunctionalityTest.java | 2 +- .../UnifiedJedisClientSideCacheTestBase.java | 4 +-- 5 files changed, 47 insertions(+), 29 deletions(-) diff --git a/src/main/java/redis/clients/jedis/UnifiedJedis.java b/src/main/java/redis/clients/jedis/UnifiedJedis.java index e9b01d1426..ae96530f04 100644 --- a/src/main/java/redis/clients/jedis/UnifiedJedis.java +++ b/src/main/java/redis/clients/jedis/UnifiedJedis.java @@ -20,6 +20,7 @@ import redis.clients.jedis.commands.SampleKeyedCommands; import redis.clients.jedis.commands.RedisModuleCommands; import redis.clients.jedis.csc.Cache; +import redis.clients.jedis.csc.CacheConnection; import redis.clients.jedis.exceptions.JedisException; import redis.clients.jedis.executors.*; import redis.clients.jedis.gears.TFunctionListParams; @@ -58,6 +59,7 @@ public class UnifiedJedis implements JedisCommands, JedisBinaryCommands, protected final CommandObjects commandObjects; private final GraphCommandObjects graphCommandObjects; private JedisBroadcastAndRoundRobinConfig broadcastAndRoundRobinConfig = null; + private final Cache cache; public UnifiedJedis() { this(new HostAndPort(Protocol.DEFAULT_HOST, Protocol.DEFAULT_PORT)); @@ -95,9 +97,9 @@ public UnifiedJedis(HostAndPort hostAndPort, JedisClientConfig clientConfig) { } @Experimental - public UnifiedJedis(HostAndPort hostAndPort, JedisClientConfig clientConfig, Cache clientSideCache) { - this(new PooledConnectionProvider(hostAndPort, clientConfig, clientSideCache), clientConfig.getRedisProtocol(), - clientSideCache); + public UnifiedJedis(HostAndPort hostAndPort, JedisClientConfig clientConfig, Cache cache) { + this(new PooledConnectionProvider(hostAndPort, clientConfig, cache), clientConfig.getRedisProtocol(), + cache); } public UnifiedJedis(ConnectionProvider provider) { @@ -109,8 +111,8 @@ protected UnifiedJedis(ConnectionProvider provider, RedisProtocol protocol) { } @Experimental - protected UnifiedJedis(ConnectionProvider provider, RedisProtocol protocol, Cache clientSideCache) { - this(new DefaultCommandExecutor(provider), provider, new CommandObjects(), protocol, clientSideCache); + protected UnifiedJedis(ConnectionProvider provider, RedisProtocol protocol, Cache cache) { + this(new DefaultCommandExecutor(provider), provider, new CommandObjects(), protocol, cache); } /** @@ -147,6 +149,11 @@ public UnifiedJedis(Connection connection) { if (proto != null) this.commandObjects.setProtocol(proto); this.graphCommandObjects = new GraphCommandObjects(this); + if(connection instanceof CacheConnection) { + this.cache = ((CacheConnection) connection).getCache(); + } else { + this.cache = null; + } } @Deprecated @@ -183,9 +190,9 @@ protected UnifiedJedis(ClusterConnectionProvider provider, int maxAttempts, Dura @Experimental protected UnifiedJedis(ClusterConnectionProvider provider, int maxAttempts, Duration maxTotalRetriesDuration, - RedisProtocol protocol, Cache clientSideCache) { + RedisProtocol protocol, Cache cache) { this(new ClusterCommandExecutor(provider, maxAttempts, maxTotalRetriesDuration), provider, - new ClusterCommandObjects(), protocol, clientSideCache); + new ClusterCommandObjects(), protocol, cache); } /** @@ -259,9 +266,9 @@ private UnifiedJedis(CommandExecutor executor, ConnectionProvider provider, Comm @Experimental private UnifiedJedis(CommandExecutor executor, ConnectionProvider provider, CommandObjects commandObjects, - RedisProtocol protocol, Cache clientSideCache) { + RedisProtocol protocol, Cache cache) { - if (clientSideCache != null && protocol != RedisProtocol.RESP3) { + if (cache != null && protocol != RedisProtocol.RESP3) { throw new IllegalArgumentException("Client-side caching is only supported with RESP3."); } @@ -274,7 +281,7 @@ private UnifiedJedis(CommandExecutor executor, ConnectionProvider provider, Comm this.graphCommandObjects = new GraphCommandObjects(this); this.graphCommandObjects.setBaseCommandArgumentsCreator((comm) -> this.commandObjects.commandArguments(comm)); - + this.cache = cache; } @Override @@ -314,6 +321,10 @@ public void setBroadcastAndRoundRobinConfig(JedisBroadcastAndRoundRobinConfig co this.commandObjects.setBroadcastAndRoundRobinConfig(this.broadcastAndRoundRobinConfig); } + public Cache getCache() { + return cache; + } + public String ping() { return checkAndBroadcastCommand(commandObjects.ping()); } diff --git a/src/main/java/redis/clients/jedis/csc/CacheConfig.java b/src/main/java/redis/clients/jedis/csc/CacheConfig.java index 0c3ccffe46..97fda3d1bd 100644 --- a/src/main/java/redis/clients/jedis/csc/CacheConfig.java +++ b/src/main/java/redis/clients/jedis/csc/CacheConfig.java @@ -14,7 +14,6 @@ public int getMaxSize() { return maxSize; } - public EvictionPolicyType getEvictionPolicyType() { return evictionPolicyType; } @@ -23,6 +22,10 @@ public Cacheable getCacheable() { return cacheable; } + public static Builder builder() { + return new Builder(); + } + public static class Builder { private int maxSize; private EvictionPolicyType evictionPolicyType = EvictionPolicyType.DEFAULT; diff --git a/src/main/java/redis/clients/jedis/csc/CacheConnection.java b/src/main/java/redis/clients/jedis/csc/CacheConnection.java index 91d4813a59..7b7516d0ee 100644 --- a/src/main/java/redis/clients/jedis/csc/CacheConnection.java +++ b/src/main/java/redis/clients/jedis/csc/CacheConnection.java @@ -14,16 +14,16 @@ public class CacheConnection extends Connection { - private final Cache clientSideCache; + private final Cache cache; private ReentrantLock lock; - public CacheConnection(final JedisSocketFactory socketFactory, JedisClientConfig clientConfig, Cache clientSideCache) { + public CacheConnection(final JedisSocketFactory socketFactory, JedisClientConfig clientConfig, Cache cache) { super(socketFactory, clientConfig); if (protocol != RedisProtocol.RESP3) { throw new JedisException("Client side caching is only supported with RESP3."); } - this.clientSideCache = Objects.requireNonNull(clientSideCache); + this.cache = Objects.requireNonNull(cache); initializeClientSideCache(); } @@ -37,7 +37,7 @@ protected void initializeFromClientConfig(JedisClientConfig config) { protected Object protocolRead(RedisInputStream inputStream) { lock.lock(); try { - return Protocol.read(inputStream, clientSideCache); + return Protocol.read(inputStream, cache); } finally { lock.unlock(); } @@ -47,7 +47,7 @@ protected Object protocolRead(RedisInputStream inputStream) { protected void protocolReadPushes(RedisInputStream inputStream) { if (lock.tryLock()) { try { - Protocol.readPushes(inputStream, clientSideCache, true); + Protocol.readPushes(inputStream, cache, true); } finally { lock.unlock(); } @@ -57,39 +57,43 @@ protected void protocolReadPushes(RedisInputStream inputStream) { @Override public void disconnect() { super.disconnect(); - clientSideCache.flush(); + cache.flush(); } @Override public T executeCommand(final CommandObject commandObject) { final CacheKey cacheKey = new CacheKey(commandObject); - if (!clientSideCache.isCacheable(cacheKey)) { - clientSideCache.getStats().nonCacheable(); + if (!cache.isCacheable(cacheKey)) { + cache.getStats().nonCacheable(); return super.executeCommand(commandObject); } - CacheEntry cacheEntry = clientSideCache.get(cacheKey); + CacheEntry cacheEntry = cache.get(cacheKey); if (cacheEntry != null) { // (probable) CACHE HIT !! cacheEntry = validateEntry(cacheEntry); if (cacheEntry != null) { // CACHE HIT confirmed !!! - clientSideCache.getStats().hit(); + cache.getStats().hit(); return cacheEntry.getValue(); } } // CACHE MISS !! - clientSideCache.getStats().miss(); + cache.getStats().miss(); T value = super.executeCommand(commandObject); if (value != null) { cacheEntry = new CacheEntry<>(cacheKey, value, this); - clientSideCache.set(cacheKey, cacheEntry); + cache.set(cacheKey, cacheEntry); // this line actually provides a deep copy of cached object instance value = cacheEntry.getValue(); } return value; } + public Cache getCache() { + return cache; + } + private void initializeClientSideCache() { sendCommand(Protocol.Command.CLIENT, "TRACKING", "ON"); String reply = getStatusCodeReply(); @@ -101,17 +105,17 @@ private void initializeClientSideCache() { private CacheEntry validateEntry(CacheEntry cacheEntry) { CacheConnection cacheOwner = cacheEntry.getConnection(); if (cacheOwner == null || cacheOwner.isBroken() || !cacheOwner.isConnected()) { - clientSideCache.delete(cacheEntry.getCacheKey()); + cache.delete(cacheEntry.getCacheKey()); return null; } else { try { cacheOwner.readPushesWithCheckingBroken(); } catch (JedisException e) { - clientSideCache.delete(cacheEntry.getCacheKey()); + cache.delete(cacheEntry.getCacheKey()); return null; } - return clientSideCache.get(cacheEntry.getCacheKey()); + return cache.get(cacheEntry.getCacheKey()); } } } diff --git a/src/test/java/redis/clients/jedis/csc/ClientSideCacheFunctionalityTest.java b/src/test/java/redis/clients/jedis/csc/ClientSideCacheFunctionalityTest.java index 6be42fcae7..63674862d5 100644 --- a/src/test/java/redis/clients/jedis/csc/ClientSideCacheFunctionalityTest.java +++ b/src/test/java/redis/clients/jedis/csc/ClientSideCacheFunctionalityTest.java @@ -303,7 +303,7 @@ public void testSequentialAccess() throws InterruptedException { ReentrantLock lock = new ReentrantLock(true); ExecutorService executorService = Executors.newFixedThreadPool(threadCount); - CacheConfig cacheConfig = new CacheConfig.Builder().maxSize(1000).build(); + CacheConfig cacheConfig = CacheConfig.builder().maxSize(1000).build(); try (JedisPooled jedis = new JedisPooled(endpoint.getHostAndPort(), clientConfig.get(), cacheConfig)) { // Submit multiple threads to perform concurrent operations CountDownLatch latch = new CountDownLatch(threadCount); diff --git a/src/test/java/redis/clients/jedis/csc/UnifiedJedisClientSideCacheTestBase.java b/src/test/java/redis/clients/jedis/csc/UnifiedJedisClientSideCacheTestBase.java index 67e83bc543..0e10bed6ad 100644 --- a/src/test/java/redis/clients/jedis/csc/UnifiedJedisClientSideCacheTestBase.java +++ b/src/test/java/redis/clients/jedis/csc/UnifiedJedisClientSideCacheTestBase.java @@ -39,7 +39,7 @@ public void tearDown() throws Exception { @Test public void simple() { - CacheConfig cacheConfig = new CacheConfig.Builder().maxSize(1000).build(); + CacheConfig cacheConfig = CacheConfig.builder().maxSize(1000).build(); try (UnifiedJedis jedis = createCachedJedis(cacheConfig)) { control.set("foo", "bar"); assertEquals("bar", jedis.get("foo")); @@ -68,7 +68,7 @@ public void simpleWithSimpleMap() { @Test public void flushAll() { - CacheConfig cacheConfig = new CacheConfig.Builder().maxSize(1000).build(); + CacheConfig cacheConfig = CacheConfig.builder().maxSize(1000).build(); try (UnifiedJedis jedis = createCachedJedis(cacheConfig)) { control.set("foo", "bar"); assertEquals("bar", jedis.get("foo")); From 8a96f0af0a134f06e060fe15bc5bd0c169168703 Mon Sep 17 00:00:00 2001 From: atakavci Date: Tue, 27 Aug 2024 11:35:24 +0300 Subject: [PATCH 6/8] add evictionpolicy to cacheconfig --- .../redis/clients/jedis/csc/CacheConfig.java | 24 ++++++++----------- .../clients/jedis/csc/CacheProvider.java | 21 ++++++---------- 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/src/main/java/redis/clients/jedis/csc/CacheConfig.java b/src/main/java/redis/clients/jedis/csc/CacheConfig.java index 97fda3d1bd..2c782a4a7c 100644 --- a/src/main/java/redis/clients/jedis/csc/CacheConfig.java +++ b/src/main/java/redis/clients/jedis/csc/CacheConfig.java @@ -2,42 +2,38 @@ public class CacheConfig { - public enum EvictionPolicyType { - DEFAULT, LRU - } - private int maxSize; - private EvictionPolicyType evictionPolicyType; private Cacheable cacheable; + private EvictionPolicy evictionPolicy; public int getMaxSize() { return maxSize; } - public EvictionPolicyType getEvictionPolicyType() { - return evictionPolicyType; - } - public Cacheable getCacheable() { return cacheable; } + public EvictionPolicy getEvictionPolicy() { + return evictionPolicy; + } + public static Builder builder() { return new Builder(); } public static class Builder { private int maxSize; - private EvictionPolicyType evictionPolicyType = EvictionPolicyType.DEFAULT; private Cacheable cacheable = DefaultCacheable.INSTANCE; + private EvictionPolicy evictionPolicy; public Builder maxSize(int maxSize) { this.maxSize = maxSize; return this; } - - public Builder evictionPolicyType(EvictionPolicyType evictionPolicyType) { - this.evictionPolicyType = evictionPolicyType; + + public Builder evictionPolicy(EvictionPolicy policy) { + this.evictionPolicy = policy; return this; } @@ -49,8 +45,8 @@ public Builder cacheable(Cacheable cacheable) { public CacheConfig build() { CacheConfig cacheConfig = new CacheConfig(); cacheConfig.maxSize = this.maxSize; - cacheConfig.evictionPolicyType = this.evictionPolicyType; cacheConfig.cacheable = this.cacheable; + cacheConfig.evictionPolicy = this.evictionPolicy; return cacheConfig; } } diff --git a/src/main/java/redis/clients/jedis/csc/CacheProvider.java b/src/main/java/redis/clients/jedis/csc/CacheProvider.java index aa20ea989e..774f772c49 100644 --- a/src/main/java/redis/clients/jedis/csc/CacheProvider.java +++ b/src/main/java/redis/clients/jedis/csc/CacheProvider.java @@ -2,29 +2,22 @@ import java.util.HashMap; -import redis.clients.jedis.csc.CacheConfig.EvictionPolicyType; - public class CacheProvider { public Cache getCache(CacheConfig config) { - switch (config.getEvictionPolicyType()) { - case LRU: - return new DefaultCache(config.getMaxSize(), new HashMap(), config.getCacheable(), - new LRUEviction(0)); - default: - return new DefaultCache(config.getMaxSize(), config.getCacheable()); - } + return getCache(config, new HashMap()); } public Cache getCache(CacheConfig config, HashMap map) { return new DefaultCache(config.getMaxSize(), map, config.getCacheable(), - getEvictionPolicy(config.getEvictionPolicyType(), config.getMaxSize())); + getEvictionPolicy(config)); } - private EvictionPolicy getEvictionPolicy(EvictionPolicyType evictionPolicyType, int initialCapacity) { - switch (evictionPolicyType) { - default: - return new LRUEviction(initialCapacity); + private EvictionPolicy getEvictionPolicy(CacheConfig config) { + if (config.getEvictionPolicy() == null) { + // It will be default to LRUEviction, until we have other eviction implementations + return new LRUEviction(config.getMaxSize()); } + return config.getEvictionPolicy(); } } \ No newline at end of file From 059eb4d88857ae989e13b480af40a62964ae6bbc Mon Sep 17 00:00:00 2001 From: atakavci Date: Tue, 27 Aug 2024 13:36:03 +0300 Subject: [PATCH 7/8] - unifiedjedis constructor with cacheconfig - wrap IOException on protocol read error --- src/main/java/redis/clients/jedis/Protocol.java | 4 +--- src/main/java/redis/clients/jedis/UnifiedJedis.java | 11 +++++++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/java/redis/clients/jedis/Protocol.java b/src/main/java/redis/clients/jedis/Protocol.java index f4cd20489a..f8bb5bfb8b 100644 --- a/src/main/java/redis/clients/jedis/Protocol.java +++ b/src/main/java/redis/clients/jedis/Protocol.java @@ -235,10 +235,8 @@ public static void readPushes(final RedisInputStream is, final Cache cache, bool is.readByte(); processPush(is, cache); } - } catch (JedisConnectionException e) { - // TODO handle it properly } catch (IOException e) { - // TODO handle it properly + throw new JedisConnectionException("Failed to read pending buffer for push messages !", e); } } else { while (is.peek(GREATER_THAN_BYTE)) { diff --git a/src/main/java/redis/clients/jedis/UnifiedJedis.java b/src/main/java/redis/clients/jedis/UnifiedJedis.java index ae96530f04..679cd8eb78 100644 --- a/src/main/java/redis/clients/jedis/UnifiedJedis.java +++ b/src/main/java/redis/clients/jedis/UnifiedJedis.java @@ -20,7 +20,9 @@ import redis.clients.jedis.commands.SampleKeyedCommands; import redis.clients.jedis.commands.RedisModuleCommands; import redis.clients.jedis.csc.Cache; +import redis.clients.jedis.csc.CacheConfig; import redis.clients.jedis.csc.CacheConnection; +import redis.clients.jedis.csc.CacheProvider; import redis.clients.jedis.exceptions.JedisException; import redis.clients.jedis.executors.*; import redis.clients.jedis.gears.TFunctionListParams; @@ -102,6 +104,11 @@ public UnifiedJedis(HostAndPort hostAndPort, JedisClientConfig clientConfig, Cac cache); } + @Experimental + public UnifiedJedis(HostAndPort hostAndPort, JedisClientConfig clientConfig, CacheConfig cacheConfig) { + this(hostAndPort, clientConfig, new CacheProvider().getCache(cacheConfig)); + } + public UnifiedJedis(ConnectionProvider provider) { this(new DefaultCommandExecutor(provider), provider); } @@ -149,7 +156,7 @@ public UnifiedJedis(Connection connection) { if (proto != null) this.commandObjects.setProtocol(proto); this.graphCommandObjects = new GraphCommandObjects(this); - if(connection instanceof CacheConnection) { + if (connection instanceof CacheConnection) { this.cache = ((CacheConnection) connection).getCache(); } else { this.cache = null; @@ -324,7 +331,7 @@ public void setBroadcastAndRoundRobinConfig(JedisBroadcastAndRoundRobinConfig co public Cache getCache() { return cache; } - + public String ping() { return checkAndBroadcastCommand(commandObjects.ping()); } From 4fe1c562831a0c413644841cac5064a20f3dde5d Mon Sep 17 00:00:00 2001 From: atakavci <58048133+atakavci@users.noreply.github.com> Date: Wed, 28 Aug 2024 17:43:21 +0300 Subject: [PATCH 8/8] fix merge issue --- src/main/java/redis/clients/jedis/csc/CacheConnection.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/redis/clients/jedis/csc/CacheConnection.java b/src/main/java/redis/clients/jedis/csc/CacheConnection.java index 6f823691da..c19dd319ec 100644 --- a/src/main/java/redis/clients/jedis/csc/CacheConnection.java +++ b/src/main/java/redis/clients/jedis/csc/CacheConnection.java @@ -82,7 +82,7 @@ public T executeCommand(final CommandObject commandObject) { cache.getStats().miss(); T value = super.executeCommand(commandObject); cacheEntry = new CacheEntry<>(cacheKey, value, this); - clientSideCache.set(cacheKey, cacheEntry); + cache.set(cacheKey, cacheEntry); // this line actually provides a deep copy of cached object instance value = cacheEntry.getValue(); return value;