CompletableFuture onTimeout получить предоставленное значение java asyn c программирование - PullRequest
1 голос
/ 04 августа 2020

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

, что я заметил, что действительно возникает исключение тайм-аута, но я понятия не имею, какой параметр

ComplianceCandidate candidate = candidates.poll();
            CompletableFuture<ComplianceCandidate> futureTask = CompletableFuture.supplyAsync(() -> candidate, pool)
                    .thenApply(Task1::doWork).thenApply(Task2::doWork).thenApply(Task3::doWork)
                    .thenApply(Task4::doWork).thenApply(ProblematicAndSlowTask::doWork).thenApply(AnotherProblematicTask::doWork)
                    .thenApply(Task6::doWork).thenApply(Task7::doWork).orTimeout(10, TimeUnit.SECONDS)
                    .exceptionally(ExceptionHandlerService::handle);
            completedList.add(futureTask);

есть способ в завершаемом будущем api, чтобы получить параметр, переданный методу doWork, который завершился ошибкой?

1 Ответ

1 голос
/ 05 августа 2020

Это невозможно, потому что, как объяснил Хольгер в комментариях, orTimeout() применяется только к CompletableFuture, на котором вы его вызываете. Нет ссылки на цепочку вызовов (или, фактически, на график), которая ведет к этому будущему.

Однако вы можете проверить все промежуточные CompletableFuture, сохранив их ссылки:

CompletableFuture<ComplianceCandidate> init = CompletableFuture.supplyAsync(() -> candidate, pool);
CompletableFuture<Result1> future1 = init.thenApply(Task1::doWork);
CompletableFuture<Result2> future2 = future1.thenApply(Task2::doWork);
…
CompletableFuture<Result7> future7 = future6.thenApply(Task7::doWork);
CompletionStage<Result7> future7OrTimeout = future7.orTimeout(10, TimeUnit.SECONDS);

, а затем проверьте каждый из них по отдельности:

CompletableFuture<ComplianceCandidate> futureTask = future7OrTimeout.exceptionally(throwable -> {
    if (!future1.isDone() || future1.isCompletedExceptionally()) {
        System.out.println("Task1 failed");
    } else if (!future2.isDone() || future2.isCompletedExceptionally()) {
        System.out.println("Task2 failed")
    } else …
});

(я позволяю вам сделать код более общим c с циклами в зависимости от ваших фактических вызовов)

...