Правильное использование Quarkus Cache с Reactive и Mutiny

Я пытаюсь перенести свой проект на Quarkus Reactive с помощью Hibernate Reactive Panache и не знаю, как поступить с кэшированием.

Мой оригинальный метод выглядел так

          @Transactional
    @CacheResult(cacheName = "subject-cache")
    public Subject getSubject(@CacheKey String subjectId) throws Exception {
        return subjectRepository.findByIdentifier(subjectId);
    }

Субъект загружается из кеша, если он доступен, по ключу кеша "subjectId".

Переход на Mutiny будет выглядеть так

          @CacheResult(cacheName = "subject-cache")
    public Uni<Subject> getSubject(@CacheKey String subjectId) {
        return subjectRepository.findByIdentifier(subjectId);
    }

Однако хранить объект Uni в кэше неправильно.

Существует также возможность внедрить кеш как bean-компонент, однако резервная функция не поддерживает возврат 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());
    }

Можно ли использовать аннотации @CacheResult с Uni/Multi и все ли правильно обрабатывается?

2 ответа

Ваш пример с @CacheResultметод, который возвращает, должен действительно работать. Реализация автоматически "удалит" Uniвведите и сохраните только Subjectв кэше.

Проблема с кэшированием Unis заключается в том, что в зависимости от того, как создается этот Uni, несколько подписок могут запускать некоторый код несколько раз. Чтобы избежать этого, вы должны запомнить Uni следующим образом:

      @CacheResult(cacheName = "subject-cache")
public Uni<Subject> getSubject(@CacheKey String subjectId) {
    return subjectRepository.findByIdentifier(subjectId)
        .memoize().indefinitely();
}

Это гарантирует, что каждая подписка на кэшированный Uni всегда будет возвращать одно и то же значение (элемент или сбой) без повторного выполнения чего-либо из исходного потока Uni.

Другие вопросы по тегам