Как повторно вызвать ненадежный API? Будет ли Completable Future более полезным, чем написание стандартного блока try catch, работающего в потоке? - PullRequest
0 голосов
/ 11 октября 2019

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

Здесь,Уведомление об ошибке может произойти сбой, и мне придется повторить уведомление об ошибке, пока я не добьюсь успеха. После чего я могу снова вызвать оригинальный API.

Я хотел создать это с помощью CompletableFuture. Правильный ли выбор библиотеки для такого рода кода? Или я должен поместить цикл try catch в бесконечный цикл, упакованный в Runnable, и выполнить его? Будет ли CompletableFuture излишним? Есть ли другая альтернатива?

1 Ответ

0 голосов
/ 13 октября 2019

Честно говоря, вопрос слишком широкий, потому что ответ действительно зависит от того, какие фреймворки вы уже используете. Дело в том, что сегодня существует много популярных фреймворков, которые обеспечивают реализацию логики повторов прямо из коробки.

Например:

Однако, если после рассмотрения альтернатив вы решили осуществить повторную попытку вручную с помощью CompletableFuture, вы определенно можете это сделать.

Например, вот простые утилиты для повторной попытки:

  • Неограниченное количество раз:
public static <T> CompletableFuture<T> retry(Throwable throwable, Function<Throwable, T> operation) {
    return CompletableFuture.supplyAsync(() -> operation.apply(throwable))
            .thenApply(CompletableFuture::completedFuture)
            .exceptionally(error -> retry(error, operation))
            .thenCompose(Function.identity());
}

Примечание: Здесь я предполагаю, что вы можетепринять какое-то решение на основе экземпляра Throwable. Следовательно, operation принимает ошибку в качестве входных данных и дает некоторый полезный результат в качестве выходных данных. В вашем случае ошибка - может быть critical API ошибка вызова или notification error, полезный результат - успешный critical API результат.

  • Фиксированное число раз (MAX_RETRIES в данном случае):
public static <T> CompletableFuture<T> retry(Throwable throwable, Function<Throwable, T> operation, int retry) {
    if (retry == MAX_RETRIES) return failedFuture(throwable);

    return CompletableFuture.supplyAsync(() -> operation.apply(throwable))
            .thenApply(CompletableFuture::completedFuture)
            .exceptionally(error -> retry(error, operation, retry + 1))
            .thenCompose(Function.identity());
}

public static <T> CompletableFuture<T> failedFuture(Throwable throwable) {
    final CompletableFuture<T> failedFuture = new CompletableFuture<>();
    failedFuture.completeExceptionally(throwable);
    return failedFuture;
}
...