/** * {@inheritDoc} */ @Override public void complete() { accept(ExecResult.complete()); }
/** * Signals this downstream, based on the given result. * * @param result the result to signal */ default void accept(ExecResult<? extends T> result) { if (result.isComplete()) { complete(); } else if (result.isError()) { error(result.getThrowable()); } else { success(result.getValue()); } }
/** * Caches the promise value and provides it to all future subscribers, if it satisfies the predicate. * <p> * This method is equivalent to using {@link #cacheResultIf(Predicate)} with a predicate that requires * a successful result and for the value to satisfy the predicate given to this method. * <p> * Non success results will not be cached. * * @param shouldCache the test for whether a successful result is cacheable * @return a caching promise * @see #cacheResultIf(Predicate) * @see #cacheResultFor(Function) * @since 1.4 */ default Promise<T> cacheIf(Predicate<? super T> shouldCache) { return cacheResultIf(r -> r.isSuccess() && shouldCache.apply(r.getValue())); }
private void receiveResult(Downstream<? super T> downstream, ExecResult<T> result) { Duration ttl = Duration.ofSeconds(0); try { ttl = ttlFunc.apply(result); } catch (Throwable e) { if (result.isError()) { //noinspection ThrowableResultOfMethodCallIgnored result.getThrowable().addSuppressed(e); } else { result = ExecResult.of(Result.error(e)); } } Instant expiresAt; if (ttl.isNegative()) { expiresAt = null; // eternal upstream = null; // release } else if (ttl.isZero()) { expiresAt = clock.instant().minus(Duration.ofSeconds(1)); } else { expiresAt = clock.instant().plus(ttl); } ref.set(new Cached<>(result, expiresAt)); pending.set(false); downstream.accept(result); tryDrain(); }
if (t.isError()) { Throwable thisError = t.getThrowable(); if (!error.compareAndSet(null, thisError)) { consumer.execute(finalI, t.getValue());
@Override public void success(T value) { receiveResult(downstream, ExecResult.of(Result.success(value))); }
@Override public Operation forEach(BiAction<? super Integer, ? super T> consumer) { return Promise.<Void>async(d -> yieldPromise(promises.iterator(), 0, (i, r) -> consumer.execute(i, r.getValue()), (i, r) -> { d.error(r.getThrowable()); return false; }, () -> d.success(null)) ).operation(); }
default void execute(Function<? super Execution, ? extends Operation> function) throws Exception { yield(e -> function.apply(e).promise()).getValueOrThrow(); }
private static <T> void yieldPromise(Iterator<? extends Promise<T>> promises, int i, BiAction<Integer, ExecResult<T>> withItem, BiFunction<Integer, ExecResult<T>, Boolean> onError, Runnable onComplete) { if (promises.hasNext()) { promises.next().result(r -> { if (r.isError()) { if (!onError.apply(i, r)) { return; } } else { withItem.execute(i, r); } yieldPromise(promises, i + 1, withItem, onError, onComplete); }); } else { onComplete.run(); } }
public void error(Throwable throwable) { receiveResult(downstream, ExecResult.of(Result.<T>error(throwable))); }
return result.get().getValueOrThrow();
@Override public void complete() { try { resultHandler.execute(ExecResult.<T>complete()); } catch (Throwable e) { DefaultPromise.throwError(e); } } });
/** * {@inheritDoc} */ @Override public void error(Throwable throwable) { accept(ExecResult.of(Result.error(throwable))); }
@Override public <T> ExecResult<T> yield(Action<? super RegistrySpec> registry, final Function<? super Execution, ? extends Promise<T>> func) throws Exception { AtomicReference<ExecResult<T>> reference = new AtomicReference<>(); CountDownLatch latch = new CountDownLatch(1); controller.fork() .register(registry) .onError(throwable -> reference.set(new ResultBackedExecResult<>(Result.<T>error(throwable)))) .onComplete(exec -> latch.countDown()) .start(execution -> { reference.set(ExecResult.complete()); Promise<T> promise = func.apply(execution); if (promise == null) { reference.set(null); } else { promise.then(t -> reference.set(new ResultBackedExecResult<>(Result.success(t)))); } }); latch.await(); return reference.get(); }
/** * {@inheritDoc} */ @Override public void success(T value) { accept(ExecResult.of(Result.success(value))); }
default Promise<Pair<ExecResult<T>, Duration>> timeResult() { return around(System::nanoTime, (start, result) -> { // protect against clock skew causing negative durations Duration duration = Duration.ofNanos(Math.max(0, System.nanoTime() - start)); return ExecResult.of(Result.success(Pair.of(result, duration))); }); }
@Override public void success(T value) { try { resultHandler.execute(ExecResult.of(Result.success(value))); } catch (Throwable e) { DefaultPromise.throwError(e); } }
@Override public void error(Throwable throwable) { try { resultHandler.execute(ExecResult.of(Result.<T>error(throwable))); } catch (Throwable e) { DefaultPromise.throwError(e); } }
yield(downstream); } catch (Throwable e) { receiveResult(downstream, ExecResult.of(Result.error(e)));