Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Autoconfigure a CompositeCacheManager with Spring Properties #41645

Closed
Crain-32 opened this issue Jul 29, 2024 · 3 comments
Closed

Autoconfigure a CompositeCacheManager with Spring Properties #41645

Crain-32 opened this issue Jul 29, 2024 · 3 comments
Labels
status: declined A suggestion or change that we don't feel we should currently apply

Comments

@Crain-32
Copy link

Spring's Caching Configuration through properties is incredibly useful. For my in particular I enjoy the ability to set it to none in my tests and have it just disable all caching. However the moment you want two CacheManagers you lose out on this ability.

I'll use an example situation where the Developer wants to have two caches. A local Caffeine Cache and a Distributed Redis Cache. Since the declaration of any Cache Manager disables auto configuration, a simple setup requires the following.

    @Bean
    @Primary
    public CacheManager compositeCacheManager(List<CacheManager> cacheManagers) { ... } // Manually configure CompositeCacheManager

    @Bean
    @ConditionalOnBean(RedisConnectionFactory.class)
    public CacheManager redisCache(RedisConnectionFactory redisConnectionFactory, CacheProperties cacheProperties) { ... } // Configure Redis Cache with Factory


    @Bean
    public CacheManager caffeineCache(CacheProperties cacheProps) { ... } // Configure Caffeine Cache

You could still leverage the CacheProperties for configuring everything but the Cache Names. However this approach isn't recommended (Properties Classes can change), and also removes a lot of quality of life changes from AutoConfiguration (Namely being able to disable it within Tests).

As most Developers will be using Unique Cache Names between their Caches, the following change seems reasonable to me.

spring:
  cache:
    type: composite # Added to the Type Enum.
    cache-names: #Can be kept, however isn't used for type==Composite
    redis:
      cache-names: my-redis-cache # Used when type==Composite, unsure how it would be used otherwise
      # Other configuration
    caffeine:
      cache-names: my-caffeine-cache # See notes on Redis Cache Configuration
      # Other Configuration
    composite:
       using: # Controls the other Types configured when type==composite
        - redis
        - caffeine
       noop-fallback: false # This is the only property in `CompositeCacheManager`, so we allow it to be configured

When spring.cache.type=composite, the following are enforced to ensure deterministic caching behavior.
All CacheManager instances being used are automatically configured to disable Lazy Cache Creation. This is so that only the CacheManager with the Cache Name provided is used.

Cache Names across all configured CacheManagers in spring.cache.composite.using are unique to the CacheManager*, so the following is invalid.

spring.cache.redis.cache-names=my-cache
spring.cache.caffeine.cache-names=my-cache

Since the above cannot resolve to a single CacheManager, the following annotation wouldn't behave deterministically.

@Cacheable("my-cache")

*This behavior could potentially be tied to if a CacheResolver bean is provided.

As you can select the CacheManager instance directly in @Cacheable, the qualifier String would be {cacheType}CacheManager, for example redisCacheManager or caffeineCacheManager. With the CompositeCacheManager using the traditional cacheManager

Current alternatives,
You can declare two CacheManagers beans with a Primary one, then utilize @Cacheable(cacheManager="my-manager"), instead of the CompositeCacheManager. However changing the location of a single Cache to a different Manager will have cascading code changes.
You can manually build the CompositeCacheManager, however you'll lose out on Auto Configuration.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jul 29, 2024
@snicoll
Copy link
Member

snicoll commented Jul 30, 2024

Thanks for the suggestion but I've already shared our position in the previous issue you've raised on this topic. Spring Boot auto-configuration will not auto-configure multiple beans of the same type until we review #15732.

Irrespective of this, your proposal sounds like programming by properties, which we usually don't recommend. Working on the above would make the auto-configuration much more complex and it already is at the moment.

@snicoll snicoll closed this as not planned Won't fix, can't repro, duplicate, stale Jul 30, 2024
@snicoll snicoll added status: declined A suggestion or change that we don't feel we should currently apply and removed status: waiting-for-triage An issue we've not yet triaged labels Jul 30, 2024
@Crain-32
Copy link
Author

I misunderstood #15732 a bit then. I read it as specifically covering specifically DataSource beans, and how it can be hard to coordinate which one to use.

I do think there is value in discussing the CompositeCacheManager some more though. It is a useful implementation that currently has no visibility to the average Spring Developer.

@snicoll
Copy link
Member

snicoll commented Jul 31, 2024

I misunderstood #15732 a bit then. I read it as specifically covering specifically DataSource beans, and how it can be hard to coordinate which one to use.

Did you read the complete history? Specifically this comment.

I do think there is value in discussing the CompositeCacheManager some more though. It is a useful implementation that currently has no visibility to the average Spring Developer.

I'd argue the average developer wouldn't use such a thing. Any implementation that we put out there has to be reasonable in terms of complexity. Your idea of using qualifier Strings is absolutely reasonable for a private implementation because you chose and live with your conventions, but not here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: declined A suggestion or change that we don't feel we should currently apply
Projects
None yet
Development

No branches or pull requests

3 participants