Reputation: 17617
I'm trying to migrate my project to Quarkus Reactive with Hibernate Reactive Panache and I'm not sure how to deal with caching.
My original method looked like this
@Transactional
@CacheResult(cacheName = "subject-cache")
public Subject getSubject(@CacheKey String subjectId) throws Exception {
return subjectRepository.findByIdentifier(subjectId);
}
The Subject is loaded from the cache, if available, by the cache key "subjectId".
Migrating to Mutiny would look like this
@CacheResult(cacheName = "subject-cache")
public Uni<Subject> getSubject(@CacheKey String subjectId) {
return subjectRepository.findByIdentifier(subjectId);
}
However, it can't be right to store the Uni object in the cache.
There is also the option to inject the cache as a bean, however, the fallback function does not support to return an Uni:
@Inject
@CacheName("subject-cache")
Cache cache;
//does not work, cache.get function requires return type Subject, not Uni<Subject>
public Uni<Subject> getSubject(String subjectId) {
return cache.get(subjectId, s -> subjectRepository.findByIdentifier(subjectId));
}
//This works, needs blocking call to repo, to return response wrapped in new Uni
public Uni<Subject> getSubject(String subjectId) {
return cache.get(subjectId, s -> subjectRepository.findByIdentifier(subjectId).await().indefinitely());
}
Can the @CacheResult annotations be used with Uni / Multi and everything is handled under the hood correctly?
Upvotes: 5
Views: 2921
Reputation: 1154
The problem with caching Unis is that depending on how this Uni is created, multiple subscriptions can trigger some code multiple times. To avoid this you have to memoize the Uni like this:
@CacheResult(cacheName = "subject-cache")
public Uni<Subject> getSubject(@CacheKey String subjectId) {
return subjectRepository.findByIdentifier(subjectId)
.memoize().indefinitely();
}
This will ensure that every subscription to the cached Uni will always return the same value (item or failure) without re-executing anything of the original Uni flow.
Upvotes: 1
Reputation: 1314
Your example with a @CacheResult
on a method that returns Uni
should actually work. The implementation will automatically "strip" the Uni
type and only store the Subject
in the cache.
Upvotes: 4