upstream.connect(downstream); };
@Override public Upstream<T> apply(Upstream<? extends T> upstream) throws Exception { return down -> { long start; if (circuitBreaker.isCallPermitted()) { start = System.nanoTime(); upstream.connect(new Downstream<T>() { @Override public void success(T value) { long durationInNanos = System.nanoTime() - start; circuitBreaker.onSuccess(durationInNanos); down.success(value); } @Override public void error(Throwable throwable) { long durationInNanos = System.nanoTime() - start; circuitBreaker.onError(durationInNanos, throwable); handleRecovery(down, throwable); } @Override public void complete() { down.complete(); } }); } else { Throwable t = new CircuitBreakerOpenException(String.format("CircuitBreaker '%s' is open", circuitBreaker.getName())); handleRecovery(down, t); } }; }
if (bulkhead.isCallPermitted()) { upstream.connect(new Downstream<T>() {
upstream.connect(new Downstream<T>() {
private void yield(final Downstream<? super T> downstream) throws Exception { upstream.connect(new Downstream<T>() { public void error(Throwable throwable) { receiveResult(downstream, ExecResult.of(Result.<T>error(throwable))); } @Override public void success(T value) { receiveResult(downstream, ExecResult.of(Result.success(value))); } @Override public void complete() { receiveResult(downstream, CompleteExecResult.get()); } }); }
private void doConnect(Downstream<? super T> downstream) { try { upstream.connect(downstream); } catch (ExecutionException e) { throw e; } catch (Exception e) { throwError(e); } }
return new DefaultOperation( promise.transform(up -> down -> up.connect(new Downstream<Void>() { @Override public void success(Void value) {
@Override public Upstream<T> apply(Upstream<? extends T> upstream) throws Exception { return down -> { long start; if (circuitBreaker.isCallPermitted()) { start = System.nanoTime(); upstream.connect(new Downstream<T>() { @Override public void success(T value) { long durationInNanos = System.nanoTime() - start; circuitBreaker.onSuccess(durationInNanos); down.success(value); } @Override public void error(Throwable throwable) { long durationInNanos = System.nanoTime() - start; circuitBreaker.onError(durationInNanos, throwable); handleRecovery(down, throwable); } @Override public void complete() { down.complete(); } }); } else { Throwable t = new CircuitBreakerOpenException(String.format("CircuitBreaker '%s' is open", circuitBreaker.getName())); handleRecovery(down, t); } }; }
if (bulkhead.isCallPermitted()) { upstream.connect(new Downstream<T>() {
/** * Transforms a failure of the given type (potentially into a value) by applying the given function to it. * <p> * This method is similar to {@link #mapError(Class, Function)}, except that it allows async transformation. * * @param function the transformation to apply to the promise failure * @return a promise * @since 1.3 */ default <E extends Throwable> Promise<T> flatMapError(Class<E> type, Function<? super E, ? extends Promise<T>> function) { return transform(up -> down -> up.connect(down.onError(throwable -> { if (type.isInstance(throwable)) { Promise<T> transformed; try { transformed = function.apply(type.cast(throwable)); } catch (Throwable t) { down.error(t); return; } transformed.connect(down); } else { down.error(throwable); } })) ); }
/** * Transforms a failure of the given type (potentially into a value) by applying the given function to it. * <p> * This method is similar to {@link #mapError(Function)}, except that it will only apply if the error is of the given type. * If the error is not of the given type, it will not be transformed and will propagate as normal. * * @param function the transformation to apply to the promise failure * @return a promise * @since 1.3 */ default <E extends Throwable> Promise<T> mapError(Class<E> type, Function<? super E, ? extends T> function) { return transform(up -> down -> up.connect(down.onError(throwable -> { if (type.isInstance(throwable)) { T transformed; try { transformed = function.apply(type.cast(throwable)); } catch (Throwable t) { down.error(t); return; } down.success(transformed); } else { down.error(throwable); } })) ); }
public static <T> Upstream<T> upstream(Upstream<T> upstream) { return downstream -> require().delimit(downstream::error, continuation -> { AsyncDownstream<T> asyncDownstream = new AsyncDownstream<>(continuation, downstream); try { upstream.connect(asyncDownstream); } catch (Throwable throwable) { if (asyncDownstream.fire()) { continuation.resume(() -> downstream.error(throwable)); } else { LOGGER.error("", new OverlappingExecutionException("promise already fulfilled", throwable)); } } } ); }
public static <T> void retryAttempt(int attemptNum, int maxAttempts, Upstream<? extends T> up, Downstream<? super T> down, BiFunction<? super Integer, ? super Throwable, Promise<Duration>> onError) throws Exception { up.connect(down.onError(e -> { if (attemptNum > maxAttempts) { down.error(e);
upstream.connect(new Downstream<T>() { @Override public void success(T value) {
upstream.connect(new Downstream<T>() {
/** * Defers the subscription of {@code this} promise until later. * <p> * When the returned promise is subscribed to, the given {@code releaser} action will be invoked. * The execution of {@code this} promise is deferred until the runnable given to the {@code releaser} is run. * <p> * It is important to note that this defers the <i>subscription</i> of the promise, not the delivery of the value. * <p> * It is generally more convenient to use {@link #throttled(Throttle)} or {@link #onYield(Runnable)} than this operation. * * @param releaser the action that will initiate the execution some time later * @return a deferred promise */ default Promise<T> defer(Action<? super Runnable> releaser) { return transform(up -> down -> Promise.async(innerDown -> releaser.execute((Runnable) () -> innerDown.success(true)) ).then(v -> up.connect(down) ) ); }
/** * Transforms a failure of the given type (potentially into a value) by applying the given function to it. * <p> * This method is similar to {@link #mapError(Function)}, except that it allows async transformation. * * @param function the transformation to apply to the promise failure * @return a promise * @since 1.3 */ default Promise<T> flatMapError(Function<? super Throwable, ? extends Promise<T>> function) { return transform(up -> down -> up.connect(down.onError(throwable -> { Promise<T> transformed; try { transformed = function.apply(throwable); } catch (Throwable t) { down.error(t); return; } transformed.connect(down); })) ); }
up.connect(down.onError(throwable -> { if (predicate.apply(throwable)) { try {
/** * Transforms a failure of the given type (potentially into a value) by applying the given function to it. * <p> * This method is similar to {@link #mapError(Predicate, Function)}, except that it allows async transformation. * * @param predicate the predicate to test against the error * @param function the transformation to apply to the promise failure * @return a promise * @since 1.6.0 */ default Promise<T> flatMapError(Predicate<? super Throwable> predicate, Function<? super Throwable, ? extends Promise<T>> function) { return transform(up -> down -> up.connect(down.onError(throwable -> { if (predicate.apply(throwable)) { Promise<T> transformed; try { transformed = function.apply(throwable); } catch (Throwable t) { down.error(t); return; } transformed.connect(down); } else { down.error(throwable); } })) ); }
/** * Transforms a failure of the given type (potentially into a value) by applying the given function to it. * <p> * This method is similar to {@link #mapError(Function)}, except that it will only apply depending if it satisfies the predicate. * If the error is not of the given type, it will not be transformed and will propagate as normal. * * @param predicate the predicate to test against the error * @param function the transformation to apply to the promise failure * @return a promise * @since 1.6.0 */ default Promise<T> mapError(Predicate<? super Throwable> predicate, Function<? super Throwable, ? extends T> function) { return transform(up -> down -> up.connect(down.onError(throwable -> { if (predicate.apply(throwable)) { T transformed; try { transformed = function.apply(throwable); } catch (Throwable t) { down.error(t); return; } down.success(transformed); } else { down.error(throwable); } })) ); }