Use error handler for reactive cache aspect

This change ensures that the cache error handler is used in case of
future-based or publisher-based asynchronous caching completing with an
exception.

Closes gh-33073
This commit is contained in:
zizare
2024-06-19 23:26:22 +02:00
committed by Simon Baslé
parent ab236c7741
commit 8974da2a5a
2 changed files with 111 additions and 4 deletions

View File

@@ -503,7 +503,10 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
if (CompletableFuture.class.isAssignableFrom(context.getMethod().getReturnType())) {
CompletableFuture<?> result = cache.retrieve(key);
if (result != null) {
return result.thenCompose(value -> (CompletableFuture<?>) evaluate(
return result.exceptionally(ex -> {
getErrorHandler().handleCacheGetError((RuntimeException) ex, cache, key);
return null;
}).thenCompose(value -> (CompletableFuture<?>) evaluate(
(value != null ? CompletableFuture.completedFuture(unwrapCacheValue(value)) : null),
invoker, method, contexts));
}
@@ -1131,12 +1134,30 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
if (adapter.isMultiValue()) {
return adapter.fromPublisher(Flux.from(Mono.fromFuture(cachedFuture))
.switchIfEmpty(Flux.defer(() -> (Flux) evaluate(null, invoker, method, contexts)))
.flatMap(v -> evaluate(valueToFlux(v, contexts), invoker, method, contexts)));
.flatMap(v -> evaluate(valueToFlux(v, contexts), invoker, method, contexts))
.onErrorResume(RuntimeException.class, ex -> {
try {
getErrorHandler().handleCacheGetError((RuntimeException) ex, cache, key);
return evaluate(null, invoker, method, contexts);
}
catch (RuntimeException exception) {
return Flux.error(exception);
}
}));
}
else {
return adapter.fromPublisher(Mono.fromFuture(cachedFuture)
.switchIfEmpty(Mono.defer(() -> (Mono) evaluate(null, invoker, method, contexts)))
.flatMap(v -> evaluate(Mono.justOrEmpty(unwrapCacheValue(v)), invoker, method, contexts)));
.flatMap(v -> evaluate(Mono.justOrEmpty(unwrapCacheValue(v)), invoker, method, contexts))
.onErrorResume(RuntimeException.class, ex -> {
try {
getErrorHandler().handleCacheGetError((RuntimeException) ex, cache, key);
return evaluate(null, invoker, method, contexts);
}
catch (RuntimeException exception) {
return Mono.error(exception);
}
}));
}
}
return NOT_HANDLED;