wave icon indicating copy to clipboard operation
wave copied to clipboard

Add distributed lazy-loading cache

Open pditommaso opened this issue 6 months ago • 0 comments

Wave uses a lazy-loading cache in several components. See #589.

In some case it's needed to share the content of the cache across backend replicas. This has been recently implemented by #588 for the RegistryAuthServiceImpl. However it requires some custom code.

The goal of this issue is to implement a lazy-loading cache that implement the logic to persist item into a shared store such Redis.

A draft implementation could be the following

 import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import redis.clients.jedis.Jedis;

import java.util.concurrent.TimeUnit;

public class HybridCache<K, V> {

    private final Cache<K, V> caffeineCache;
    private final Jedis jedis;

    public HybridCache() {
        this.caffeineCache = Caffeine.newBuilder()
                .expireAfterWrite(10, TimeUnit.MINUTES)
                .maximumSize(100)
                .build();

        this.jedis = new Jedis("localhost", 6379);
    }

    public void put(K key, V value) {
        // Put in Caffeine
        caffeineCache.put(key, value);

        // Put in Redis
        jedis.set(key.toString(), value.toString());
    }

    public V get(K key, Class<V> clazz) {
        // Try to get from Caffeine
        V value = caffeineCache.getIfPresent(key);
        if (value != null) {
            return value;
        }

        // If not in Caffeine, try to get from Redis
        String redisValue = jedis.get(key.toString());
        if (redisValue != null) {
            // Optionally, convert the Redis value from String to the desired type
            // For simplicity, assuming V is String. Modify as needed.
            value = clazz.cast(redisValue);
            // Put in Caffeine for faster subsequent access
            caffeineCache.put(key, value);
        }
        return value;
    }

    public void invalidate(K key) {
        // Invalidate in Caffeine
        caffeineCache.invalidate(key);

        // Remove from Redis
        jedis.del(key.toString());
    }

}

Requirement

pditommaso avatar Aug 06 '24 09:08 pditommaso