Reactor retry не вызывает метод для повторной попытки - PullRequest
1 голос
/ 25 сентября 2019

У меня есть метод, который всегда возвращает Mono.error

private Mono<String> doSomething() {
        System.out.println("doSomething");
        return Mono.error(new Error());
}

Я пытался повторить выполнение 3 раза

Mono<String> mono =
                myClass.doSomething()
                        .doOnSubscribe(x -> System.out.println("Subscribe"))
                        .retryWhen(companion -> companion
                                .doOnNext(s -> System.out.println(s + " at " + LocalTime.now()))
                                .zipWith(Flux.range(1, 4), (error, index) -> {
                                    if (index < 4) return index;
                                    else throw Exceptions.propagate(error);
                                })
                                .flatMap(index -> Mono.delay(Duration.ofMillis(index * 100)))
                                .doOnNext(s -> System.out.println("retried at " + LocalTime.now()))
                        );

        mono.block();

Однако doSomething печатается только один раз, аSubscribe напечатано 4 раза (1 x в начале, 3 x попытки)

Как можно повторно подписаться без выполнения метода?

Что я хочу сделать, это выполнить doSomethingпри каждой попытке

Ответы [ 2 ]

0 голосов
/ 26 сентября 2019

Для выполнения doSomething при каждой повторной попытке вы можете использовать оператор defer в сочетании с retryWhen:

Mono.defer(() -> myClass.doSomething()
                        .doOnSubscribe(x -> System.out.println("Subscribe")))
    .retryWhen(// rest of the code

По сути,retryWhen оператор работает путем повторной подписки на источник Mono, а оператор defer каждый раз переоценивает лямбдуесть новая подписка .Итак, в конце вы получите желаемое поведение.

0 голосов
/ 26 сентября 2019

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

Здесь предпочтительнее выполнить рефакторинг вашего кода, чтобы любая сторонаэффекты подписываются на Mono, например:

private Mono<String> doSomething() {
    return Mono.<String>error(new Error()).doOnSubscribe(s -> System.out.println("doSomething"));
}

Однако, если это невозможно, вы можете заставить doSomething() выполняться как есть при каждой повторной попытке, используя его в качестве поставщика.и выравнивание результата.Если вы хотите пойти по этому маршруту, замените:

myClass.doSomething()

... на:

Mono.fromSupplier(myClass::doSomething).flatMap(p->p)
...