Reactor - Как использовать filterWhen и по-прежнему передавать значение для целей регистрации, если оно не проходит фильтр? - PullRequest
1 голос
/ 16 февраля 2020

Я пытаюсь найти правильный способ сделать следующее.

  • Я хочу проверить, существует ли запись в базе данных с помощью name, который является глобальным вторичным индексом. (Допустим, первичный ключ - id).
  • Если уже есть элемент с name, зарегистрируйте id и name и вернет ошибку.
  • Если нет элемента с указанным name, тогда продолжайте.

Прямо сейчас, структура кода выглядит следующим образом.

private fun checkExistingData(name: String): Mono<QueryResponse> {
  return repo.getDataByName(name)
    .filterWhen { Mono.just(!it.hasItems()) }
    .switchIfEmpty {
      // log the existing id and name from QueryResponse
      Mono.error(SomeCustomException))
    }
    .flatMap {
      // proceed
    }
}

Как видите, если я Если вы хотите записать id в предложении switchIfEmpty, мне нужно сделать в нем repo.getDataByName(name), чтобы иметь возможность получить элемент и получить id элемента. Очевидно, это неэффективно, так как я уже делаю это до switchIfEmpty.

Как правильно это сделать?

1 Ответ

0 голосов
/ 19 февраля 2020

В ожидании дополнительной информации об API QueryResponse я собираюсь предположить несколько вещей: - getDataByName возвращает Mono<QueryResponse>. Это Mono ВСЕГДА оценивается, ie всегда выдает ровно один QueryResponse, либо данные не найдены - QueryResponse#items - это то, что я буду использовать в своем примере для доступа к собственно строкам. Я также предполагаю, что он возвращает Flux<Item>

Во-первых, filterWhen здесь бесполезен, поскольку у нас также есть метод filter(boolean). Я думаю, что логику обратного фильтра c, возможно, немного сложнее понять.

Почему бы не сделать все в flatMap вместо этого?

private fun checkExistingData(name: String): Mono<QueryResponse> {
  return repo.getDataByName(name)
    .flatMap {
       if (it.hasItems())
         it.items()
           .single()
           .doOnNext(existing -> logExisting(existing.id(), existing.name())
           .then(Mono.error(SomeCustomException)
        else
          proceed()
    }   
}
...