mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-28 18:19:05 +00:00
Stop truncating Flux results to first element with @CacheEvict
Prior to this commit, ReactiveCachingHandler.processCacheEvicts() adapted every reactive return value via Mono.from(), which subscribes for only the first element and cancels the upstream Publisher. For a @CacheEvict method that returns a Flux, this silently truncated the returned sequence to its first element. In addition, the `#result` variable in `condition` SpEL expressions was bound to only that first emitted element. To address that, this commit mirrors the existing multi-value handling in processPutRequest(). When the adapter reports isMultiValue(), a side Subscriber is subscribed via publish().refCount(2) that exhausts the Flux and collects its values into a List for eviction, while the original, unmodified Flux is returned to the caller. Consequently, the `#result` variable in `condition` SpEL expressions for a Flux-returning @CacheEvict method is now the full List of emitted elements rather than just the first element, making it consistent with @Cacheable and @CachePut. This commit also improves spr14235AdaptsToReactorFlux() in CacheReproTests. Previously it exercised @CacheEvict only with a single-element Flux and never asserted on the returned sequence. Now it uses a multi-element Flux and verifies that all elements are both returned to the caller and visible to the `condition` expression. Last but not least, this commit documents the aforementioned `#result`/Flux semantics in @CacheEvict's Javadoc and in the reference manual, since both were previously invalid or incomplete for this scenario. Closes gh-37309
This commit is contained in:
@@ -381,10 +381,12 @@ available to the context so that you can use them for key and conditional comput
|
||||
|
||||
| `result`
|
||||
| Evaluation context
|
||||
| The result of the method call (the value to be cached). Only available in `unless`
|
||||
expressions, `cache put` expressions (to compute the `key`), or `cache evict`
|
||||
expressions (when `beforeInvocation` is `false`). For supported wrappers (such as
|
||||
`Optional`), `#result` refers to the actual object, not the wrapper.
|
||||
| The result of the method call (the value to be cached, or evaluated for eviction). Only
|
||||
available in `unless` expressions, `cache put` expressions (`key`, `condition`, or
|
||||
`unless`), or `cache evict` expressions (`key` or `condition`, when `beforeInvocation`
|
||||
is `false`). For supported wrappers (such as `Optional`), `#result` refers to the
|
||||
actual object, not the wrapper. For a method returning a `Flux`, `#result` refers to a
|
||||
`List` containing all values collected from the `Flux`.
|
||||
| `#result`
|
||||
|===
|
||||
|
||||
@@ -464,7 +466,12 @@ not the case with `@Cacheable` which adds data to the cache or updates data in t
|
||||
and, thus, requires a result.
|
||||
|
||||
As of 6.1, `@CacheEvict` takes `CompletableFuture` and reactive return types into account,
|
||||
performing an after-invocation evict operation whenever processing has completed.
|
||||
performing an after-invocation evict operation whenever processing has completed. As with
|
||||
`@Cacheable` and `@CachePut`, for a method returning a `Flux`, all emitted elements are
|
||||
collected into a `List` before the evict operation is performed. When `beforeInvocation`
|
||||
is `false`, that same `List` is what the `condition` SpEL expression sees as the
|
||||
`#result`. Either way, the `Flux` returned to the caller is unaffected by this collection
|
||||
process.
|
||||
|
||||
TIP: When `@CacheEvict` is combined with `@Retryable`, the retry advice is applied
|
||||
outermost, so eviction runs again on every retry attempt -- and, with
|
||||
|
||||
Reference in New Issue
Block a user