Сочетание двух моно с условием - PullRequest
3 голосов
/ 15 мая 2019

Я хочу объединить результат из двух Mono на основе некоторого условия.Оба Mono являются результатами WebClient вызовов:

  • Первый - это один вызов, ожидающий быстрого ответа.
  • Второй - это комбинация нескольких вызовов с медленнымresponse.

Идея "отменить" второй Mono, если результат первого удовлетворяет некоторому условию, чтобы сэкономить время и избежать ненужных сетевых вызовов.Если первого Mono результата недостаточно, zip его со вторым Mono.

Пример кода Kotlin, объясняющий мою идею:

fun getResult(): Mono<Result> {

    val trivialResultMono: Mono<Result> = webClient.getResult()

    val nonTrivialResultMono: Mono<Result> = webClient
            .getResult()
            .flatMap { webClient.getResult1(it) }
            .flatMap { webClient.getResult2(it) }
            .flatMap { webClient.getResult2(it) }

    //here I need to check if trivial result satisfies some condition,
    //for example trivialResult.size > 5 if it's true I just return
    //trivialResultMono from getResult() function, 
    //it it's false something like this:
    return Mono.zip(trivialResultMono, nonTrivialResultMono) { trivialResult, nonTrivialResult ->
        trivialResult + nonTrivialResult
    }

}

ОБНОВЛЕНИЕ:

Для большей ясности предположим, что trivialResult приходит через 1 секунду, а неTrivialResult через 2 секунды.Я хочу получить свой окончательный результат за 1 секунду в случае trivialResult.size > 5 и за 2 секунды в противном случае.

Используя только Mono.zip(trivialResultMono, nonTrivialResultMono), я всегда получу свой окончательный результат через 2 секунды.

Используя filter + switchIfEmpty, это займет 1 секунду, если trivialResult.size > 5, и 3 секунды в противном случае.Пожалуйста, поправьте меня, если я ошибаюсь.

Ответы [ 2 ]

1 голос
/ 15 мая 2019

Вы можете отфильтровать trivialResultMono и применить switchIfEmpty оператор

return trivialResultMono
        .filter(trivialResult -> trivialResult.size > 5)
        .switchIfEmpty(Mono.zip(...))

Обновление для merge подхода:

Mono<Result> zipResultMono = Mono.zip...

return Flux.merge(
        trivialResultMono.map(trivialResult -> Tuples.of(1, trivialResult)),
        zipResultMono.map(zipResult -> Tuples.of(2, zipResult)))
        .filter(tuple ->
                (tuple.getT1().equals(1) && tuple.getT2().size > 5) ||
                        tuple.getT1().equals(2))
        .next()
        .map(Tuple2::getT2);

Вы можете пропустить конвертацию в Tuple2, если zipResult всегда имеет размер больше 5

0 голосов
/ 16 мая 2019

Вы можете достичь этого с помощью flatMap и map:

trivial.flatMap(trivialResult -> {
  if (trivialResult.size > 5) {
    return Mono.just(trivialResult);
  } else {
    return nonTrivial.map(nonTrivialResult -> trivialResult + nonTrivialResult);
  }
});
...