Реактор, как повторить шаг n раз, если условие выполнено - PullRequest
0 голосов
/ 16 января 2019

Пожалуйста, помогите мне с реактором Мне нужно проверить одно условие макс n раз и вернуть окончательный результат после всех

Я обнаружил, что реактор имеет дополнительный модуль реактора

https://projectreactor.io/docs/extra/snapshot/api/reactor/retry/Repeat.html

имеет конструкцию Repeat.create(java.util.function.Predicate<? super RepeatContext<T>> predicate, long n) Функция повтора, которая повторяется n раз, только если предикат возвращает true.

Это похоже на правильное решение, но я не могу понять, где должно быть
действие, которое я хочу повторить? У меня есть Flux со многими действиями, но я хочу повторить только один

Пожалуйста, приведите пример кода

Спасибо

private int culculateNextResult(some params) {
          // some implementation  
 }



private Boolean compareResults(int prevRes, int nextRes) {
          // some implementation
 }

 public Flux<Boolean> run(some params, Flux<Integer> prevResults){

      return prevResults.map(elem -> compareResults(elem, culculateNextResult(some params)));

 // THIS LOGIC SHOULD BE REPEATED N times if compareResults(elem,       
 // culculateNextResult(some params))) == false, if true, we don't need 
// to repeat 
     }

Я хочу повторять CompareResults (elem, culculateNextResult (некоторые параметры))), пока оно не станет истинным. но максимум в n раз и в результате возвращает Flux

1 Ответ

0 голосов
/ 24 марта 2019

Flux.repeat и Mono.repeat будут повторно подписываться на источник, поэтому каждый предыдущий шаг источника будет повторяться с новой подпиской.

Так как calculateNextResult и compareResults оба являются синхроннымиОперации в вашем примере, вы можете использовать простой цикл for для повторения ...

    public Flux<Boolean> run(some params, Flux<Integer> prevResults){
        return prevResults.map(elem -> {
            for (int i = 0; i < 5; i++) {
                if (compareResults(elem, calculateNextResult(some params))) {
                    return true;
                }
            }
            return false;
        });
    }

Если бы calculateNextResult или compareResults были реактивными методами, возвращающими Mono, то вы могли бы использовать flatMap вместо map и используйте один из Mono.repeat* методов.

Например, что-то вроде этого:

    private Mono<Integer> calculateNextResult(some params) {
        // some implementation
    }

    private Mono<Boolean> compareResults(int prevRes, int nextRes) {
        // some implementation
    }
    public Flux<Boolean> run(some params, Flux<Integer> prevResults){

        return prevResults.flatMap(prevResult -> 

            calculateNextResult(some params)
                    .flatMap(nextResult -> compareResults(prevResult, nextResult))
                    .filter(comparisonResult -> comparisonResult)
                    .repeatWhenEmpty(Repeat.times(5))
                    .defaultIfEmpty(false));
    }

В этом примере repeatWhenEmpty вызовет новую подписку на Mono, созданную в flatMap, что приведет к calculateNextResultпересчитать (при условии, что Mono, возвращенный из calculateNextResult, настроен для расчета значения для каждой подписки).

...