Skip to content

Commit

Permalink
- added 'Cache' interface and 'DefaultCache' implementation in regard…
Browse files Browse the repository at this point in the history
… to design doc

- added 'EvictionPolicy' interface and LRU implementation
- move cache object validation and cache control stuf from 'ClientSideCache' into 'CacheConnection'
- make guava and caffeine caches experimental
  • Loading branch information
atakavci committed Jul 26, 2024
1 parent f7c4fbf commit fc137c0
Show file tree
Hide file tree
Showing 29 changed files with 699 additions and 293 deletions.
6 changes: 3 additions & 3 deletions src/main/java/redis/clients/jedis/ConnectionFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
import org.slf4j.LoggerFactory;

import redis.clients.jedis.annots.Experimental;
import redis.clients.jedis.csc.Cache;
import redis.clients.jedis.csc.CacheConnection;
import redis.clients.jedis.csc.ClientSideCache;
import redis.clients.jedis.exceptions.JedisException;

/**
Expand All @@ -20,7 +20,7 @@ public class ConnectionFactory implements PooledObjectFactory<Connection> {

private final JedisSocketFactory jedisSocketFactory;
private final JedisClientConfig clientConfig;
private ClientSideCache clientSideCache = null;
private Cache clientSideCache = null;

public ConnectionFactory(final HostAndPort hostAndPort) {
this.clientConfig = DefaultJedisClientConfig.builder().build();
Expand All @@ -33,7 +33,7 @@ public ConnectionFactory(final HostAndPort hostAndPort, final JedisClientConfig
}

@Experimental
public ConnectionFactory(final HostAndPort hostAndPort, final JedisClientConfig clientConfig, ClientSideCache csCache) {
public ConnectionFactory(final HostAndPort hostAndPort, final JedisClientConfig clientConfig, Cache csCache) {
this.clientConfig = clientConfig;
this.jedisSocketFactory = new DefaultJedisSocketFactory(hostAndPort, this.clientConfig);
this.clientSideCache = csCache;
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/redis/clients/jedis/ConnectionPool.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import redis.clients.jedis.annots.Experimental;
import redis.clients.jedis.csc.ClientSideCache;
import redis.clients.jedis.csc.Cache;
import redis.clients.jedis.util.Pool;

public class ConnectionPool extends Pool<Connection> {
Expand All @@ -13,7 +13,7 @@ public ConnectionPool(HostAndPort hostAndPort, JedisClientConfig clientConfig) {
}

@Experimental
public ConnectionPool(HostAndPort hostAndPort, JedisClientConfig clientConfig, ClientSideCache clientSideCache) {
public ConnectionPool(HostAndPort hostAndPort, JedisClientConfig clientConfig, Cache clientSideCache) {
this(new ConnectionFactory(hostAndPort, clientConfig, clientSideCache));
}

Expand All @@ -27,7 +27,7 @@ public ConnectionPool(HostAndPort hostAndPort, JedisClientConfig clientConfig,
}

@Experimental
public ConnectionPool(HostAndPort hostAndPort, JedisClientConfig clientConfig, ClientSideCache clientSideCache,
public ConnectionPool(HostAndPort hostAndPort, JedisClientConfig clientConfig, Cache clientSideCache,
GenericObjectPoolConfig<Connection> poolConfig) {
this(new ConnectionFactory(hostAndPort, clientConfig, clientSideCache), poolConfig);
}
Expand Down
14 changes: 7 additions & 7 deletions src/main/java/redis/clients/jedis/JedisCluster.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import redis.clients.jedis.annots.Experimental;
import redis.clients.jedis.providers.ClusterConnectionProvider;
import redis.clients.jedis.csc.ClientSideCache;
import redis.clients.jedis.csc.Cache;
import redis.clients.jedis.util.JedisClusterCRC16;

public class JedisCluster extends UnifiedJedis {
Expand Down Expand Up @@ -218,35 +218,35 @@ private JedisCluster(ClusterConnectionProvider provider, int maxAttempts, Durati
}

@Experimental
public JedisCluster(Set<HostAndPort> clusterNodes, JedisClientConfig clientConfig, ClientSideCache clientSideCache) {
public JedisCluster(Set<HostAndPort> clusterNodes, JedisClientConfig clientConfig, Cache clientSideCache) {
this(clusterNodes, clientConfig, clientSideCache, DEFAULT_MAX_ATTEMPTS,
Duration.ofMillis(DEFAULT_MAX_ATTEMPTS * clientConfig.getSocketTimeoutMillis()));
}

@Experimental
public JedisCluster(Set<HostAndPort> clusterNodes, JedisClientConfig clientConfig, ClientSideCache clientSideCache,
public JedisCluster(Set<HostAndPort> clusterNodes, JedisClientConfig clientConfig, Cache clientSideCache,
int maxAttempts, Duration maxTotalRetriesDuration) {
this(new ClusterConnectionProvider(clusterNodes, clientConfig, clientSideCache), maxAttempts, maxTotalRetriesDuration,
clientConfig.getRedisProtocol(), clientSideCache);
}

@Experimental
public JedisCluster(Set<HostAndPort> clusterNodes, JedisClientConfig clientConfig, ClientSideCache clientSideCache,
public JedisCluster(Set<HostAndPort> clusterNodes, JedisClientConfig clientConfig, Cache clientSideCache,
int maxAttempts, Duration maxTotalRetriesDuration, GenericObjectPoolConfig<Connection> poolConfig) {
this(new ClusterConnectionProvider(clusterNodes, clientConfig, clientSideCache, poolConfig),
maxAttempts, maxTotalRetriesDuration, clientConfig.getRedisProtocol(), clientSideCache);
}

@Experimental
public JedisCluster(Set<HostAndPort> clusterNodes, JedisClientConfig clientConfig, ClientSideCache clientSideCache,
public JedisCluster(Set<HostAndPort> clusterNodes, JedisClientConfig clientConfig, Cache clientSideCache,
GenericObjectPoolConfig<Connection> poolConfig) {
this(new ClusterConnectionProvider(clusterNodes, clientConfig, clientSideCache, poolConfig),
DEFAULT_MAX_ATTEMPTS, Duration.ofMillis(DEFAULT_MAX_ATTEMPTS * clientConfig.getSocketTimeoutMillis()),
clientConfig.getRedisProtocol(), clientSideCache);
}

@Experimental
public JedisCluster(Set<HostAndPort> clusterNodes, JedisClientConfig clientConfig, ClientSideCache clientSideCache,
public JedisCluster(Set<HostAndPort> clusterNodes, JedisClientConfig clientConfig, Cache clientSideCache,
GenericObjectPoolConfig<Connection> poolConfig, Duration topologyRefreshPeriod, int maxAttempts,
Duration maxTotalRetriesDuration) {
this(new ClusterConnectionProvider(clusterNodes, clientConfig, clientSideCache, poolConfig, topologyRefreshPeriod),
Expand All @@ -255,7 +255,7 @@ public JedisCluster(Set<HostAndPort> clusterNodes, JedisClientConfig clientConfi

@Experimental
private JedisCluster(ClusterConnectionProvider provider, int maxAttempts, Duration maxTotalRetriesDuration,
RedisProtocol protocol, ClientSideCache clientSideCache) {
RedisProtocol protocol, Cache clientSideCache) {
super(provider, maxAttempts, maxTotalRetriesDuration, protocol, clientSideCache);
}

Expand Down
10 changes: 5 additions & 5 deletions src/main/java/redis/clients/jedis/JedisClusterInfoCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

import redis.clients.jedis.annots.Experimental;
import redis.clients.jedis.annots.Internal;
import redis.clients.jedis.csc.ClientSideCache;
import redis.clients.jedis.csc.Cache;
import redis.clients.jedis.exceptions.JedisClusterOperationException;
import redis.clients.jedis.exceptions.JedisException;
import redis.clients.jedis.util.SafeEncoder;
Expand All @@ -48,7 +48,7 @@ public class JedisClusterInfoCache {

private final GenericObjectPoolConfig<Connection> poolConfig;
private final JedisClientConfig clientConfig;
private final ClientSideCache clientSideCache;
private final Cache clientSideCache;
private final Set<HostAndPort> startNodes;

private static final int MASTER_NODE_INDEX = 2;
Expand All @@ -72,7 +72,7 @@ public JedisClusterInfoCache(final JedisClientConfig clientConfig, final Set<Hos
}

@Experimental
public JedisClusterInfoCache(final JedisClientConfig clientConfig, ClientSideCache clientSideCache,
public JedisClusterInfoCache(final JedisClientConfig clientConfig, Cache clientSideCache,
final Set<HostAndPort> startNodes) {
this(clientConfig, clientSideCache, null, startNodes);
}
Expand All @@ -83,7 +83,7 @@ public JedisClusterInfoCache(final JedisClientConfig clientConfig,
}

@Experimental
public JedisClusterInfoCache(final JedisClientConfig clientConfig, ClientSideCache clientSideCache,
public JedisClusterInfoCache(final JedisClientConfig clientConfig, Cache clientSideCache,
final GenericObjectPoolConfig<Connection> poolConfig, final Set<HostAndPort> startNodes) {
this(clientConfig, clientSideCache, poolConfig, startNodes, null);
}
Expand All @@ -95,7 +95,7 @@ public JedisClusterInfoCache(final JedisClientConfig clientConfig,
}

@Experimental
public JedisClusterInfoCache(final JedisClientConfig clientConfig, ClientSideCache clientSideCache,
public JedisClusterInfoCache(final JedisClientConfig clientConfig, Cache clientSideCache,
final GenericObjectPoolConfig<Connection> poolConfig, final Set<HostAndPort> startNodes,
final Duration topologyRefreshPeriod) {
this.poolConfig = poolConfig;
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/redis/clients/jedis/JedisPooled.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import redis.clients.jedis.annots.Experimental;
import redis.clients.jedis.csc.ClientSideCache;
import redis.clients.jedis.csc.Cache;
import redis.clients.jedis.providers.PooledConnectionProvider;
import redis.clients.jedis.util.JedisURIHelper;
import redis.clients.jedis.util.Pool;
Expand Down Expand Up @@ -78,7 +78,7 @@ public JedisPooled(final HostAndPort hostAndPort, final JedisClientConfig client
}

@Experimental
public JedisPooled(final HostAndPort hostAndPort, final JedisClientConfig clientConfig, ClientSideCache clientSideCache) {
public JedisPooled(final HostAndPort hostAndPort, final JedisClientConfig clientConfig, Cache clientSideCache) {
super(hostAndPort, clientConfig, clientSideCache);
}

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

@Experimental
public JedisPooled(final HostAndPort hostAndPort, final JedisClientConfig clientConfig, ClientSideCache clientSideCache,
public JedisPooled(final HostAndPort hostAndPort, final JedisClientConfig clientConfig, Cache clientSideCache,
final GenericObjectPoolConfig<Connection> poolConfig) {
super(new PooledConnectionProvider(hostAndPort, clientConfig, clientSideCache, poolConfig),
clientConfig.getRedisProtocol(), clientSideCache);
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/redis/clients/jedis/JedisSentineled.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import java.util.Set;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import redis.clients.jedis.annots.Experimental;
import redis.clients.jedis.csc.ClientSideCache;
import redis.clients.jedis.csc.Cache;
import redis.clients.jedis.providers.SentineledConnectionProvider;

public class JedisSentineled extends UnifiedJedis {
Expand All @@ -15,7 +15,7 @@ public JedisSentineled(String masterName, final JedisClientConfig masterClientCo
}

@Experimental
public JedisSentineled(String masterName, final JedisClientConfig masterClientConfig, ClientSideCache clientSideCache,
public JedisSentineled(String masterName, final JedisClientConfig masterClientConfig, Cache clientSideCache,
Set<HostAndPort> sentinels, final JedisClientConfig sentinelClientConfig) {
super(new SentineledConnectionProvider(masterName, masterClientConfig, clientSideCache,
sentinels, sentinelClientConfig), masterClientConfig.getRedisProtocol(), clientSideCache);
Expand All @@ -29,7 +29,7 @@ public JedisSentineled(String masterName, final JedisClientConfig masterClientCo
}

@Experimental
public JedisSentineled(String masterName, final JedisClientConfig masterClientConfig, ClientSideCache clientSideCache,
public JedisSentineled(String masterName, final JedisClientConfig masterClientConfig, Cache clientSideCache,
final GenericObjectPoolConfig<Connection> poolConfig,
Set<HostAndPort> sentinels, final JedisClientConfig sentinelClientConfig) {
super(new SentineledConnectionProvider(masterName, masterClientConfig, clientSideCache, poolConfig,
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/redis/clients/jedis/Protocol.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import redis.clients.jedis.exceptions.*;
import redis.clients.jedis.args.Rawable;
import redis.clients.jedis.commands.ProtocolCommand;
import redis.clients.jedis.csc.ClientSideCache;
import redis.clients.jedis.csc.Cache;
import redis.clients.jedis.util.KeyValue;
import redis.clients.jedis.util.RedisInputStream;
import redis.clients.jedis.util.RedisOutputStream;
Expand Down Expand Up @@ -214,7 +214,7 @@ public static Object read(final RedisInputStream is) {
}

@Experimental
public static void readPushes(final RedisInputStream is, final ClientSideCache cache, boolean onlyPendingBuffer) {
public static void readPushes(final RedisInputStream is, final Cache cache, boolean onlyPendingBuffer) {
if (onlyPendingBuffer) {
try {
while (is.available() > 0 && is.peek(GREATER_THAN_BYTE)) {
Expand All @@ -234,11 +234,11 @@ public static void readPushes(final RedisInputStream is, final ClientSideCache c
}
}

private static void processPush(final RedisInputStream is, ClientSideCache cache) {
private static void processPush(final RedisInputStream is, Cache cache) {
List<Object> list = processMultiBulkReply(is);
if (list.size() == 2 && list.get(0) instanceof byte[]
&& Arrays.equals(INVALIDATE_BYTES, (byte[]) list.get(0))) {
cache.invalidate((List) list.get(1));
cache.deleteByRedisKeys((List) list.get(1));
}
}

Expand Down
12 changes: 6 additions & 6 deletions src/main/java/redis/clients/jedis/UnifiedJedis.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import redis.clients.jedis.commands.SampleBinaryKeyedCommands;
import redis.clients.jedis.commands.SampleKeyedCommands;
import redis.clients.jedis.commands.RedisModuleCommands;
import redis.clients.jedis.csc.ClientSideCache;
import redis.clients.jedis.csc.Cache;
import redis.clients.jedis.exceptions.JedisException;
import redis.clients.jedis.executors.*;
import redis.clients.jedis.gears.TFunctionListParams;
Expand Down Expand Up @@ -95,7 +95,7 @@ public UnifiedJedis(HostAndPort hostAndPort, JedisClientConfig clientConfig) {
}

@Experimental
public UnifiedJedis(HostAndPort hostAndPort, JedisClientConfig clientConfig, ClientSideCache clientSideCache) {
public UnifiedJedis(HostAndPort hostAndPort, JedisClientConfig clientConfig, Cache clientSideCache) {
this(new PooledConnectionProvider(hostAndPort, clientConfig, clientSideCache), clientConfig.getRedisProtocol(),
clientSideCache);
}
Expand All @@ -109,7 +109,7 @@ protected UnifiedJedis(ConnectionProvider provider, RedisProtocol protocol) {
}

@Experimental
protected UnifiedJedis(ConnectionProvider provider, RedisProtocol protocol, ClientSideCache clientSideCache) {
protected UnifiedJedis(ConnectionProvider provider, RedisProtocol protocol, Cache clientSideCache) {
this(new DefaultCommandExecutor(provider), provider, new CommandObjects(), protocol, clientSideCache);
}

Expand Down Expand Up @@ -183,7 +183,7 @@ protected UnifiedJedis(ClusterConnectionProvider provider, int maxAttempts, Dura

@Experimental
protected UnifiedJedis(ClusterConnectionProvider provider, int maxAttempts, Duration maxTotalRetriesDuration,
RedisProtocol protocol, ClientSideCache clientSideCache) {
RedisProtocol protocol, Cache clientSideCache) {
this(new ClusterCommandExecutor(provider, maxAttempts, maxTotalRetriesDuration), provider,
new ClusterCommandObjects(), protocol, clientSideCache);
}
Expand Down Expand Up @@ -254,12 +254,12 @@ public UnifiedJedis(CommandExecutor executor, ConnectionProvider provider, Comma
@Experimental
private UnifiedJedis(CommandExecutor executor, ConnectionProvider provider, CommandObjects commandObjects,
RedisProtocol protocol) {
this(executor, provider, commandObjects, protocol, (ClientSideCache) null);
this(executor, provider, commandObjects, protocol, (Cache) null);
}

@Experimental
private UnifiedJedis(CommandExecutor executor, ConnectionProvider provider, CommandObjects commandObjects,
RedisProtocol protocol, ClientSideCache clientSideCache) {
RedisProtocol protocol, Cache clientSideCache) {

if (clientSideCache != null && protocol != RedisProtocol.RESP3) {
throw new IllegalArgumentException("Client-side caching is only supported with RESP3.");
Expand Down
98 changes: 98 additions & 0 deletions src/main/java/redis/clients/jedis/csc/Cache.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package redis.clients.jedis.csc;

import java.util.Collection;
import java.util.List;

/**
* The cache that is used by a connection
*/
public interface Cache {

/**
* @return The size of the cache
*/
int getMaxSize();

/**
* @return The current size of the cache
*/
int getSize();

/**
* @return All the entries within the cache
*/
Collection<CacheEntry> getCacheEntries();

/**
* Fetches a value from the cache
*
* @param cacheKey The key within the cache
* @return The entry within the cache
*/
CacheEntry get(CacheKey cacheKey);

/**
* Puts a value into the cache
*
* @param cacheKey The key by which the value can be accessed within the cache
* @param value The value to be put into the cache
* @return The cache entry
*/
CacheEntry set(CacheKey cacheKey, CacheEntry value);

/**
* Delete an entry by cache key
* @param cacheKey The cache key of the entry in the cache
* @return True if the entry could be deleted, false if the entry wasn't found.
*/
Boolean delete(CacheKey cacheKey);

/**
* Delete entries by cache key from the cache
*
* @param cacheKeys The cache keys of the entries that should be deleted
* @return True for every entry that could be deleted. False if the entry was not there.
*/
List<Boolean> delete(List<CacheKey> cacheKeys);

/**
* Delete an entry by the Redis key from the cache
*
* @param key The Redis key as binary
* @return True if the entry could be deleted. False if the entry was not there.
*/
List<CacheKey> deleteByRedisKey(Object key);

/**
* Delete entries by the Redis key from the cache
*
* @param keys The Redis keys as binaries
* @return True for every entry that could be deleted. False if the entry was not there.
*/
List<CacheKey> deleteByRedisKeys(List keys);

/**
* Flushes the entire cache
*
* @return Return the number of entries that were flushed
*/
int flush();

/**
* @param cacheKey The key of the cache entry
* @return True if the entry is cachable, false otherwise
*/
Boolean isCacheable(CacheKey cacheKey);

/**
*
* @param cacheKey The key of the cache entry
* @return True if the cache already contains the key
*/
Boolean hasCacheKey(CacheKey cacheKey);

/**
* @return The eviction policy that is used by the cache
*/
EvictionPolicy getEvictionPolicy();
}
Loading

0 comments on commit fc137c0

Please sign in to comment.