Повторить логику в случае сбоя - Spring Reactor

Как выполнить модульный тест RetryWhen,

 public Mono<List<Transaction>> get(String id) {
            return class
                    .get(id).log()
                 .retryWhen(throwableFlux -> throwableFlux) 
                .zipWith(Flux.range(min, max + 1), (error, retry) -> new RetryException(error, retry))
                .flatMap(retryException -> {
                    if(retryException.getRetries() == max + 1) {
                        throw Exceptions.propagate(retryException.getThrowable());
                    } else if (isClientException(retryException.getThrowable())){
                        return Flux.empty();
                    }
                    return Mono.delay(Duration.ofMinutes( new Double(multiplier * retryException.getRetries()).longValue()));
                }));
        }

Как мне использовать StepVerifier для проверки этого метода?

Другой способ реализовать логику повтора,

throwableFlux.takeWhile(throwable -> !isClientException(throwable))
            .flatMap(e -> {
                if(count.get() >= max + 1) {
                    throw Exceptions.propagate(e);
                }
                LOG.info("Retrying in..");
                return Mono.delay(Duration.ofMinutes(new Double(multiplier * count.getAndAdd(1)).longValue()));
            });

person Bharath    schedule 10.05.2017    source источник
comment
разве в строке retryWhen нет дополнительной закрывающей скобки? вы применяете zipWith.flatMap к throwableFlux, верно?   -  person Simon Baslé    schedule 12.05.2017


Ответы (2)


Вы имеете в виду тестирование RetryHelper, примененного через retryWhen?

Вы, безусловно, можете использовать StepVerifier для проверки такой повторной попытки, содержащей последовательность, да. Вы также можете проверить количество (повторных) подписок, используя AtomicLong в сочетании с doOnSubscribe непосредственно перед retryWhen (это поможет установить количество подписок, сделанных для повторного использования источника).

Обратите внимание, что мы только что добавили такую ​​утилиту-конструктор для retryWhen и repeatWhen, но в проекте reactor-extra (в настоящее время в версии 3.1.0.BUILD-SNAPSHOT)

person Simon Baslé    schedule 10.05.2017
comment
ой. я просто расширил код. я смог протестировать свой код с помощью stepverifier.withVirtualTime. Я возвращаю Flux.empty() - (без операции) для определенного условия. Есть ли рекомендации, как это проверить? - person Bharath; 10.05.2017
comment
тестирование пустого, но конечного потока так же просто, как verifyComplete() без предварительного ожидания, кроме expectSubscription - person Simon Baslé; 10.05.2017
comment
FirstStep.verifyComplete() или type.expectSubscription().verifyComplete() застревают в бесконечном цикле for в DefaultStepVerifierBuilder.pollTaskEventOrComplete. - person Bharath; 10.05.2017
comment
ах, как плохо, если вы используете виртуальное время, вам, вероятно, все еще нужно переводить часы через thenAwait или expectNoEvent (я полагаю, вы добавили задержки и повторные попытки в свою цепочку, которая просто оказывается пустой из-за других операторов?) - person Simon Baslé; 12.05.2017
comment
да. это правильно. потому что, если бы часы не переводились на определенный тип ошибки, я не вызывал бы expectNoEvent. благодарю вас. - person Bharath; 16.05.2017
comment
Кстати, я смог реализовать альтернативный способ применения логики повторных попыток. я обновил свой первоначальный ответ. - person Bharath; 16.05.2017

Вот как я смог протестировать этот код.

FirstStep.expectSubscription().expectNoEvent(java.time.Duration.ofMinutes(1)).expectNoEvent(Duration.ofMinutes(3)).verifyError()

Мы могли бы использовать thenAwait(Duration.ofDays(1)) выше, но у expectNoEvent есть преимущество, гарантирующее, что ничего не произошло раньше, чем должно было произойти.

http://projectreactor.io/docs/core/snapshot/reference/docs/index.html#error.handling

person Bharath    schedule 10.05.2017