I wanted to retry my function call whenever it get failed in some duration of time. What is the best way do this. Is this will work fine.
CompletableFuture.runAsync(() -> {
for (int i = 0; i < 3; i++) {
try {
dndService.initateDNDRequest(transactionId, circle, category, "PREPAID");
break;
} catch (Exception e) {
try {
TimeUnit.SECONDS.sleep(10);//wait for few minutes while next attempt
} catch (InterruptedException e1) {
LOGGER.error("Error while retrying request for DND.");
}
LOGGER.error("Request retry for DND count"+i);
}
}
}, executor);
You should not put an executor’s worker thread to sleep
.
One solution to schedule a new attempt, would be
Executor executor; // … the actual executor
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
Executor afterTenSeconds
= r -> ses.schedule(() -> executor.execute(r), 10, TimeUnit.SECONDS);
Runnable primaryAction
= () -> dndService.initateDNDRequest(transactionId, circle, category, "PREPAID");
CompletableFuture<Void> cf = CompletableFuture.runAsync(primaryAction, executor);
for(int i = 0; i < 3; i++) {
cf = cf.handle((v,t) -> t == null? CompletableFuture.completedFuture(v):
CompletableFuture.runAsync(primaryAction, afterTenSeconds))
.thenCompose(Function.identity());
}
Then handle
action will schedule a new attempt, to be executed after the timeout (ten seconds) in the failure case. The thenCompose(Function.identity())
is necessary as there is no single method to combine handle
and compose
semantics.
Note that starting with Java 9, you can create the delayed executor as simple as
Executor afterTenSeconds = CompletableFuture.delayedExecutor(10,TimeUnit.SECONDS,executor);
without the need to deal with ScheduledExecutorService
yourself.