FutureUtils { public static <T> CompletableFuture<T> orTimeout(CompletableFuture<T> future, long timeout, TimeUnit timeUnit) { final ScheduledFuture<?> timeoutFuture = Delayer.delay(new Timeout(future), timeout, timeUnit); future.whenComplete((T value, Throwable throwable) -> { if (!timeoutFuture.isDone()) { timeoutFuture.cancel(false); } }); return future; }  static CompletableFuture<T> retry(
			final Supplier<CompletableFuture<T>> operation,
			final int retries,
			final Executor executor); static CompletableFuture<T> retryWithDelay(
			final Supplier<CompletableFuture<T>> operation,
			final int retries,
			final Time retryDelay,
			final ScheduledExecutor scheduledExecutor); static ConjunctFuture<Collection<T>> combineAll(Collection<? extends CompletableFuture<? extends T>> futures); static ConjunctFuture<Void> waitForAll(Collection<? extends CompletableFuture<?>> futures); static CompletableFuture<T> completedExceptionally(Throwable cause); static FiniteDuration toFiniteDuration(Time time); static Time toTime(FiniteDuration finiteDuration); static CompletableFuture<T> toJava(Future<T> scalaFuture); static CompletableFuture<T> orTimeout(CompletableFuture<T> future, long timeout, TimeUnit timeUnit);  }
@Test public void testOrTimeout() throws Exception { final CompletableFuture<String> future = new CompletableFuture<>(); final long timeout = 10L; FutureUtils.orTimeout(future, timeout, TimeUnit.MILLISECONDS); try { future.get(); } catch (ExecutionException e) { assertTrue(ExceptionUtils.stripExecutionException(e) instanceof TimeoutException); } }