private static <T> FlowFuture<T> _exponentialWithJitter(Flows.SerCallable<FlowFuture<T>> op, RetrySettings settings, int attempt) { Flow f = Flows.currentFlow(); try { FlowFuture<T> future = op.call(); return future.exceptionallyCompose((e) -> { if (attempt < settings.maxAttempts) { long delay_max = (long) Math.min( settings.timeUnit.toMillis(settings.delayMaxDuration), settings.timeUnit.toMillis(settings.delayBaseDuration) * Math.pow(2, attempt)); long delay = new Random().longs(1, 0, delay_max).findFirst().getAsLong(); return f.delay(delay, TimeUnit.MILLISECONDS) .thenCompose((a) -> _exponentialWithJitter(op, settings, attempt + 1)); } else { return f.failedFuture(new RuntimeException()); } }); } catch (Exception ex) { return f.failedFuture(new RuntimeException()); } }