Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple Caffeine LoadingCaches added to Spring CaffeineCacheManager

I'm looking to add several distinct LoadingCache's to a Spring CacheManager, however I don't see how this is possible using CaffeineCacheManager. It appears that only a single loader is possible for refreshing content, however I need separate loaders for each cache. Is it possible to add multiple loading caches to a Spring cache manager? If so, then how?

CaffeineCacheManager cacheManage = new CaffeineCacheManager();

LoadingCache<String, Optional<Edition>> loadingCache1 = 
            Caffeine.newBuilder()
            .maximumSize(150)
            .refreshAfterWrite(5, TimeUnit.MINUTES)
            .build(test -> this.testRepo.find(test));

LoadingCache<String, Optional<Edition>> loadingCache2 = 
            Caffeine.newBuilder()
            .maximumSize(150)
            .refreshAfterWrite(5, TimeUnit.MINUTES)
            .build(test2 -> this.testRepo.find2(test2));

// How do I add to cache manager, and specify a name?
like image 698
Steve Avatar asked Jun 12 '17 19:06

Steve


People also ask

How do spring boots use caffeine?

The primary way to use caching in Spring Boot is with the @Cacheable annotation. This annotation works on any method of a Spring bean (or even the entire class). It instructs the registered cache manager to store the result of the method call in a cache.

Can you set a specific specification per cache using caffeine in Spring Boot?

And Spring Boot comes with a CaffeineCacheManager . So, ideally, that's all you need – you just create a cache manager bean and you have caching for your @Cacheable annotated-methods. However, the provided cache manager allows you to configure just one cache specification.

Is caffeine cache thread-safe?

Cache entries are manually added using get(Object, Function) or put(Object, Object) , and are stored in the cache until either evicted or manually invalidated. Implementations of this interface are expected to be thread-safe, and can be safely accessed by multiple concurrent threads.

What is maximum size in caffeine cache?

Caffeine Cache Configuration The Caffeine spec define the cache maximum size as 500 and a time to live of 10 minutes.


2 Answers

Yes it is possible. Since you need to fine tune every cache, you are probably better at defining them yourself. Back to your example, the next step would be:

SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.setCaches(Arrays.asList(
    new CaffeineCache("first", loadingCache1),
    new CaffeineCache("second", loadingCache2)));

And then you can use that as usual, e.g.

@Cacheable("first")
public Foo load(String id) { ... }

If you are using Spring Boot, you can just expose the individual cache as beans (so org.springframework.cache.Cache implementations) and we'll detect them and create a SimpleCacheManager automatically for you.

Note that this strategy allows you to use the cache abstraction with different implementations. first could be a caffeine cache and second a cache from another provider.

like image 170
Stephane Nicoll Avatar answered Oct 02 '22 14:10

Stephane Nicoll


Having this class will allow you to use @Cacheable("cacheA") where you want as normal:

@EnableCaching
@Configuration
public class CacheConfiguration {

    @Bean
    public CacheManager cacheManager() {
        CaffeineCacheManager manager = new CaffeineCacheManager();
        manager.registerCustomCache("cacheA", defaultCache());
        manager.registerCustomCache("cacheB", bigCache());
        manager.registerCustomCache("cacheC", longCache());
        // to avoid dynamic caches and be sure each name is assigned to a specific config (dynamic = false)
        // throws error when tries to use a new cache
        manager.setCacheNames(Collections.emptyList());
        return manager;
    }

    private static Cache<Object, Object> defaultCache() {
        return Caffeine.newBuilder()
                .maximumSize(1000)
                .expireAfterWrite(5, TimeUnit.MINUTES)
                .build();
    }

    private static Cache<Object, Object> bigCache() {
        return Caffeine.newBuilder()
                .maximumSize(5000)
                .expireAfterWrite(5, TimeUnit.MINUTES)
                .build();
    }

    private static Cache<Object, Object> longCache() {
        return Caffeine.newBuilder()
                .maximumSize(1000)
                .expireAfterWrite(1, TimeUnit.HOURS)
                .build();
    }
}
like image 25
rado Avatar answered Oct 02 '22 15:10

rado