Я использую Spring WebClient и реактор проекта, чтобы делать неблокирующие вызовы к списку URL-адресов. Мои требования:
- Асинхронно вызывать GET для списка URL-адресов
- Регистрируйте URL-адрес при вызове каждого URL-адреса
- Зарегистрируйте URL-адрес вызова, который приводит к исключению
- Зарегистрируйте URL-адрес успешного вызова
- Зарегистрируйте URL-адрес вызова, который приводит к статусу HTTP, отличному от 2xx.
- Отправьте электронное письмо, содержащее список URL-адресов, вызов которых привел к исключению или статусу HTTP, отличному от 2xx.
Вот моя попытка сделать это:
List<Mono<ClientResponse>> restCalls = new ArrayList<>();
List<String> failedUrls = new ArrayList<>();
for (String serviceUrl : serviceUrls.getServiceUrls()) {
restCalls.add(
webClientBuilder
.build()
.get()
.uri(serviceUrl)
.exchange()
.doOnSubscribe(c -> log.info("calling service URL {}", serviceUrl))
.doOnSuccess(response -> log.info("{} success status {}", serviceUrl, response.statusCode().toString()))
.doOnError(response -> {log.info("{} error status {}", serviceUrl, response); failedUrls.add(serviceUrl);}));
}
Flux.fromIterable(restCalls)
.map((data) -> data.subscribe())
.onErrorContinue((throwable, e) -> {
log.info("Exception for URL {}", ((WebClientResponseException) throwable).getRequest().getURI());
failedUrls.add(serviceUrl);
})
.collectList()
.subscribe((data) -> {
log.info("all called");
email.send("Failed URLs are {}", failedUrls);
});
Проблема в том, что письмо отправляется до ответа на звонок. Как я могу дождаться завершения всех вызовов URL-адресов до вызова email.send
?
.map((data) -> data.subscribe())
на.flatMap(data -> data)
, потому что подписка запускает действие, но не позволяет наблюдать его результат (возвращаемое значение только для отмены запущенного задания). Также остерегайтесь onErrorContinue (дополнительная информация по этой проблеме). Я постараюсь добавить более развернутый ответ позже, но, возможно, этих подсказок вам будет достаточно для решения ваших проблем. - person amanin   schedule 31.03.2021