Provide request-scoped cache support for WebFlux coroutines #36004
+1,109 −0
Add this suggestion to a batch that can be applied as a single commit. This suggestion is invalid because no changes were made to the code. Suggestions cannot be applied while the pull request is closed. Suggestions cannot be applied while viewing a subset of changes. Only one suggestion per line can be applied in a batch. Add this suggestion to a batch that can be applied as a single commit. Applying suggestions on deleted lines is not supported. You must change the existing code in this line in order to create a valid suggestion. Outdated suggestions cannot be applied. This suggestion has been applied or marked resolved. Suggestions cannot be applied from pending reviews. Suggestions cannot be applied on multi-line comments. Suggestions cannot be applied while the pull request is queued to merge. Suggestion cannot be applied right now. Please check back later.
Background
Coroutines support for
@Cacheablewas introduced in 466c8d8 and refined in 6becfe2 (following Spring AOP coroutines support in c8169e5).While this effectively solves long-lived cache use cases for suspend methods, it does not easily translate to request-scoped caching.
Although there is no direct support for standard methods as well, request-scoped caching is typically achieved by defining a
@RequestScopeCacheManagerbean. However, since@RequestScopemechanism relies on thread local, the same approach is not suitable for coroutines, that can suspend and resume on different threads.For a coroutine-based WebFlux server, a potential workaround involves explicitly adding to the request coroutine context the required resolved data (or a lazy resolver), using a custom coroutine context element, or manually passing it down the call stack as a method argument. However, this explicit approach strictly ties the implementation of a service - that may need this shared data at a deep request execution level - with the request context. It may also require a huge refactor to pass all the way down the required shared data, if the caching need emerges late in development. Additionally, for Kotlin WebFlux based GraphQL frameworks, clients can batch independent queries within the same request to save network resources, preventing an explicit design on server side that is able to cache common data for each possible queries combination.
For a better separation of concerns, we might prefer instead to inject the data provider as a service dependency, but still avoid duplicated executions within the same request.
Proposal
This PR provides request-scoped, proxy-based, cache management capability to Spring WebFlux servers leveraging Kotlin coroutines.
Specifically, suspend methods of Spring beans can now be annotated with
@CoRequestCacheable.The cached result is tied to the web request coroutine context, ensuring that each new incoming web request triggers a new execution of the annotated method.
The required infrastructure can be enabled by using
@EnableCoRequestCachingon a configuration class.Although the proposed implementation could not fit in the already existing
@Cacheableinfrastructure, individual components have been reused or extended whenever possible to maintain consistency.