Search in sources :

Example 91 with Action0

use of rx.functions.Action0 in project Hystrix by Netflix.

the class AbstractCommand method executeCommandAndObserve.

/**
 * This decorates "Hystrix" functionality around the run() Observable.
 *
 * @return R
 */
private Observable<R> executeCommandAndObserve(final AbstractCommand<R> _cmd) {
    final HystrixRequestContext currentRequestContext = HystrixRequestContext.getContextForCurrentThread();
    final Action1<R> markEmits = new Action1<R>() {

        @Override
        public void call(R r) {
            if (shouldOutputOnNextEvents()) {
                executionResult = executionResult.addEvent(HystrixEventType.EMIT);
                eventNotifier.markEvent(HystrixEventType.EMIT, commandKey);
            }
            if (commandIsScalar()) {
                long latency = System.currentTimeMillis() - executionResult.getStartTimestamp();
                eventNotifier.markEvent(HystrixEventType.SUCCESS, commandKey);
                executionResult = executionResult.addEvent((int) latency, HystrixEventType.SUCCESS);
                eventNotifier.markCommandExecution(getCommandKey(), properties.executionIsolationStrategy().get(), (int) latency, executionResult.getOrderedList());
                circuitBreaker.markSuccess();
            }
        }
    };
    final Action0 markOnCompleted = new Action0() {

        @Override
        public void call() {
            if (!commandIsScalar()) {
                long latency = System.currentTimeMillis() - executionResult.getStartTimestamp();
                eventNotifier.markEvent(HystrixEventType.SUCCESS, commandKey);
                executionResult = executionResult.addEvent((int) latency, HystrixEventType.SUCCESS);
                eventNotifier.markCommandExecution(getCommandKey(), properties.executionIsolationStrategy().get(), (int) latency, executionResult.getOrderedList());
                circuitBreaker.markSuccess();
            }
        }
    };
    final Func1<Throwable, Observable<R>> handleFallback = new Func1<Throwable, Observable<R>>() {

        @Override
        public Observable<R> call(Throwable t) {
            circuitBreaker.markNonSuccess();
            Exception e = getExceptionFromThrowable(t);
            executionResult = executionResult.setExecutionException(e);
            if (e instanceof RejectedExecutionException) {
                return handleThreadPoolRejectionViaFallback(e);
            } else if (t instanceof HystrixTimeoutException) {
                return handleTimeoutViaFallback();
            } else if (t instanceof HystrixBadRequestException) {
                return handleBadRequestByEmittingError(e);
            } else {
                /*
                     * Treat HystrixBadRequestException from ExecutionHook like a plain HystrixBadRequestException.
                     */
                if (e instanceof HystrixBadRequestException) {
                    eventNotifier.markEvent(HystrixEventType.BAD_REQUEST, commandKey);
                    return Observable.error(e);
                }
                return handleFailureViaFallback(e);
            }
        }
    };
    final Action1<Notification<? super R>> setRequestContext = new Action1<Notification<? super R>>() {

        @Override
        public void call(Notification<? super R> rNotification) {
            setRequestContextIfNeeded(currentRequestContext);
        }
    };
    Observable<R> execution;
    if (properties.executionTimeoutEnabled().get()) {
        execution = executeCommandWithSpecifiedIsolation(_cmd).lift(new HystrixObservableTimeoutOperator<R>(_cmd));
    } else {
        execution = executeCommandWithSpecifiedIsolation(_cmd);
    }
    return execution.doOnNext(markEmits).doOnCompleted(markOnCompleted).onErrorResumeNext(handleFallback).doOnEach(setRequestContext);
}
Also used : Action0(rx.functions.Action0) Action1(rx.functions.Action1) HystrixTimeoutException(com.netflix.hystrix.exception.HystrixTimeoutException) Observable(rx.Observable) TimeoutException(java.util.concurrent.TimeoutException) HystrixRuntimeException(com.netflix.hystrix.exception.HystrixRuntimeException) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) HystrixBadRequestException(com.netflix.hystrix.exception.HystrixBadRequestException) HystrixTimeoutException(com.netflix.hystrix.exception.HystrixTimeoutException) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) Notification(rx.Notification) HystrixBadRequestException(com.netflix.hystrix.exception.HystrixBadRequestException) HystrixRequestContext(com.netflix.hystrix.strategy.concurrency.HystrixRequestContext) Func1(rx.functions.Func1)

Example 92 with Action0

use of rx.functions.Action0 in project Hystrix by Netflix.

the class HystrixCollapser method observe.

/**
 * Used for asynchronous execution with a callback by subscribing to the {@link Observable}.
 * <p>
 * This eagerly starts execution the same as {@link #queue()} and {@link #execute()}.
 * A lazy {@link Observable} can be obtained from {@link #toObservable()}.
 * <p>
 * <b>Callback Scheduling</b>
 * <p>
 * <ul>
 * <li>When using {@link ExecutionIsolationStrategy#THREAD} this defaults to using {@link Schedulers#computation()} for callbacks.</li>
 * <li>When using {@link ExecutionIsolationStrategy#SEMAPHORE} this defaults to using {@link Schedulers#immediate()} for callbacks.</li>
 * </ul>
 * Use {@link #toObservable(rx.Scheduler)} to schedule the callback differently.
 * <p>
 * See https://github.com/Netflix/RxJava/wiki for more information.
 *
 * @return {@code Observable<R>} that executes and calls back with the result of of {@link HystrixCommand}{@code <BatchReturnType>} execution after passing through {@link #mapResponseToRequests}
 *         to transform the {@code <BatchReturnType>} into {@code <ResponseType>}
 */
public Observable<ResponseType> observe() {
    // use a ReplaySubject to buffer the eagerly subscribed-to Observable
    ReplaySubject<ResponseType> subject = ReplaySubject.create();
    // eagerly kick off subscription
    final Subscription underlyingSubscription = toObservable().subscribe(subject);
    // return the subject that can be subscribed to later while the execution has already started
    return subject.doOnUnsubscribe(new Action0() {

        @Override
        public void call() {
            underlyingSubscription.unsubscribe();
        }
    });
}
Also used : Action0(rx.functions.Action0) Subscription(rx.Subscription)

Example 93 with Action0

use of rx.functions.Action0 in project Hystrix by Netflix.

the class HystrixCommandTest method testUnsubscribingDownstreamOperatorStillResultsInSuccessEventType.

/**
 * Some RxJava operators like take(n), zip receive data in an onNext from upstream and immediately unsubscribe.
 * When upstream is a HystrixCommand, Hystrix may get that unsubscribe before it gets to its onCompleted.
 * This should still be marked as a HystrixEventType.SUCCESS.
 */
@Test
public void testUnsubscribingDownstreamOperatorStillResultsInSuccessEventType() throws InterruptedException {
    HystrixCommand<Integer> cmd = getCommand(ExecutionIsolationStrategy.THREAD, AbstractTestHystrixCommand.ExecutionResult.SUCCESS, 100, AbstractTestHystrixCommand.FallbackResult.UNIMPLEMENTED);
    Observable<Integer> o = cmd.toObservable().doOnNext(new Action1<Integer>() {

        @Override
        public void call(Integer i) {
            System.out.println(Thread.currentThread().getName() + " : " + System.currentTimeMillis() + " CMD OnNext : " + i);
        }
    }).doOnError(new Action1<Throwable>() {

        @Override
        public void call(Throwable throwable) {
            System.out.println(Thread.currentThread().getName() + " : " + System.currentTimeMillis() + " CMD OnError : " + throwable);
        }
    }).doOnCompleted(new Action0() {

        @Override
        public void call() {
            System.out.println(Thread.currentThread().getName() + " : " + System.currentTimeMillis() + " CMD OnCompleted");
        }
    }).doOnSubscribe(new Action0() {

        @Override
        public void call() {
            System.out.println(Thread.currentThread().getName() + " : " + System.currentTimeMillis() + " CMD OnSubscribe");
        }
    }).doOnUnsubscribe(new Action0() {

        @Override
        public void call() {
            System.out.println(Thread.currentThread().getName() + " : " + System.currentTimeMillis() + " CMD OnUnsubscribe");
        }
    }).take(1).observeOn(Schedulers.io()).map(new Func1<Integer, Integer>() {

        @Override
        public Integer call(Integer i) {
            System.out.println(Thread.currentThread().getName() + " : " + System.currentTimeMillis() + " : Doing some more computation in the onNext!!");
            try {
                Thread.sleep(100);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
            return i;
        }
    });
    final CountDownLatch latch = new CountDownLatch(1);
    o.doOnSubscribe(new Action0() {

        @Override
        public void call() {
            System.out.println(Thread.currentThread().getName() + " : " + System.currentTimeMillis() + " : OnSubscribe");
        }
    }).doOnUnsubscribe(new Action0() {

        @Override
        public void call() {
            System.out.println(Thread.currentThread().getName() + " : " + System.currentTimeMillis() + " : OnUnsubscribe");
        }
    }).subscribe(new Subscriber<Integer>() {

        @Override
        public void onCompleted() {
            System.out.println(Thread.currentThread().getName() + " : " + System.currentTimeMillis() + " : OnCompleted");
            latch.countDown();
        }

        @Override
        public void onError(Throwable e) {
            System.out.println(Thread.currentThread().getName() + " : " + System.currentTimeMillis() + " : OnError : " + e);
            latch.countDown();
        }

        @Override
        public void onNext(Integer i) {
            System.out.println(Thread.currentThread().getName() + " : " + System.currentTimeMillis() + " : OnNext : " + i);
        }
    });
    latch.await(1000, TimeUnit.MILLISECONDS);
    System.out.println("ReqLog : " + HystrixRequestLog.getCurrentRequest().getExecutedCommandsAsString());
    assertTrue(cmd.isExecutedInThread());
    assertCommandExecutionEvents(cmd, HystrixEventType.SUCCESS);
}
Also used : AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Action0(rx.functions.Action0) Action1(rx.functions.Action1) CountDownLatch(java.util.concurrent.CountDownLatch) Test(org.junit.Test)

Example 94 with Action0

use of rx.functions.Action0 in project Hystrix by Netflix.

the class HystrixCommandTest method testRequestThenTwoCacheHitsAllUnsubscribed.

@Test
public void testRequestThenTwoCacheHitsAllUnsubscribed() {
    AsyncCacheableCommand original = new AsyncCacheableCommand("foo");
    AsyncCacheableCommand fromCache1 = new AsyncCacheableCommand("foo");
    AsyncCacheableCommand fromCache2 = new AsyncCacheableCommand("foo");
    final CountDownLatch originalLatch = new CountDownLatch(1);
    final CountDownLatch fromCache1Latch = new CountDownLatch(1);
    final CountDownLatch fromCache2Latch = new CountDownLatch(1);
    Observable<Boolean> originalObservable = original.toObservable();
    Observable<Boolean> fromCache1Observable = fromCache1.toObservable();
    Observable<Boolean> fromCache2Observable = fromCache2.toObservable();
    Subscription originalSubscription = originalObservable.doOnUnsubscribe(new Action0() {

        @Override
        public void call() {
            System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " Test.Original Unsubscribe");
            originalLatch.countDown();
        }
    }).subscribe(new Subscriber<Boolean>() {

        @Override
        public void onCompleted() {
            System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " Test.Original OnCompleted");
            originalLatch.countDown();
        }

        @Override
        public void onError(Throwable e) {
            System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " Test.Original OnError : " + e);
            originalLatch.countDown();
        }

        @Override
        public void onNext(Boolean b) {
            System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " Test.Original OnNext : " + b);
        }
    });
    Subscription fromCache1Subscription = fromCache1Observable.doOnUnsubscribe(new Action0() {

        @Override
        public void call() {
            System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " Test.FromCache1 Unsubscribe");
            fromCache1Latch.countDown();
        }
    }).subscribe(new Subscriber<Boolean>() {

        @Override
        public void onCompleted() {
            System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " Test.FromCache1 OnCompleted");
            fromCache1Latch.countDown();
        }

        @Override
        public void onError(Throwable e) {
            System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " Test.FromCache1 OnError : " + e);
            fromCache1Latch.countDown();
        }

        @Override
        public void onNext(Boolean b) {
            System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " Test.FromCache1 OnNext : " + b);
        }
    });
    Subscription fromCache2Subscription = fromCache2Observable.doOnUnsubscribe(new Action0() {

        @Override
        public void call() {
            System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " Test.FromCache2 Unsubscribe");
            fromCache2Latch.countDown();
        }
    }).subscribe(new Subscriber<Boolean>() {

        @Override
        public void onCompleted() {
            System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " Test.FromCache2 OnCompleted");
            fromCache2Latch.countDown();
        }

        @Override
        public void onError(Throwable e) {
            System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " Test.FromCache2 OnError : " + e);
            fromCache2Latch.countDown();
        }

        @Override
        public void onNext(Boolean b) {
            System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " Test.FromCache2 OnNext : " + b);
        }
    });
    try {
        Thread.sleep(10);
        originalSubscription.unsubscribe();
        fromCache1Subscription.unsubscribe();
        fromCache2Subscription.unsubscribe();
        assertTrue(originalLatch.await(200, TimeUnit.MILLISECONDS));
        assertTrue(fromCache1Latch.await(200, TimeUnit.MILLISECONDS));
        assertTrue(fromCache2Latch.await(200, TimeUnit.MILLISECONDS));
        System.out.println("ReqLog : " + HystrixRequestLog.getCurrentRequest().getExecutedCommandsAsString());
        assertEquals("Number of execution semaphores in use (original)", 0, original.getExecutionSemaphore().getNumberOfPermitsUsed());
        assertEquals("Number of fallback semaphores in use (original)", 0, original.getFallbackSemaphore().getNumberOfPermitsUsed());
        assertFalse(original.isExecutionComplete());
        assertTrue(original.isExecutedInThread());
        System.out.println("FEE : " + original.getFailedExecutionException());
        if (original.getFailedExecutionException() != null) {
            original.getFailedExecutionException().printStackTrace();
        }
        assertNull(original.getFailedExecutionException());
        assertNull(original.getExecutionException());
        assertTrue(original.getExecutionTimeInMilliseconds() > -1);
        assertFalse(original.isSuccessfulExecution());
        assertCommandExecutionEvents(original, HystrixEventType.CANCELLED);
        // assertTrue(original.isCancelled());   //underlying work  This doesn't work yet
        assertEquals(0, original.metrics.getCurrentConcurrentExecutionCount());
        assertEquals("Number of execution semaphores in use (fromCache1)", 0, fromCache1.getExecutionSemaphore().getNumberOfPermitsUsed());
        assertEquals("Number of fallback semaphores in use (fromCache1)", 0, fromCache1.getFallbackSemaphore().getNumberOfPermitsUsed());
        assertFalse(fromCache1.isExecutionComplete());
        assertFalse(fromCache1.isExecutedInThread());
        assertEquals(null, fromCache1.getFailedExecutionException());
        assertNull(fromCache1.getExecutionException());
        assertCommandExecutionEvents(fromCache1, HystrixEventType.RESPONSE_FROM_CACHE, HystrixEventType.CANCELLED);
        assertTrue(fromCache1.getExecutionTimeInMilliseconds() == -1);
        assertFalse(fromCache1.isSuccessfulExecution());
        assertEquals(0, fromCache1.metrics.getCurrentConcurrentExecutionCount());
        assertEquals("Number of execution semaphores in use (fromCache2)", 0, fromCache2.getExecutionSemaphore().getNumberOfPermitsUsed());
        assertEquals("Number of fallback semaphores in use (fromCache2)", 0, fromCache2.getFallbackSemaphore().getNumberOfPermitsUsed());
        assertFalse(fromCache2.isExecutionComplete());
        assertFalse(fromCache2.isExecutedInThread());
        assertEquals(null, fromCache2.getFailedExecutionException());
        assertNull(fromCache2.getExecutionException());
        assertCommandExecutionEvents(fromCache2, HystrixEventType.RESPONSE_FROM_CACHE, HystrixEventType.CANCELLED);
        assertTrue(fromCache2.getExecutionTimeInMilliseconds() == -1);
        assertFalse(fromCache2.isSuccessfulExecution());
        assertEquals(0, fromCache2.metrics.getCurrentConcurrentExecutionCount());
        assertSaneHystrixRequestLog(3);
    } catch (InterruptedException ex) {
        ex.printStackTrace();
    }
}
Also used : Action0(rx.functions.Action0) CountDownLatch(java.util.concurrent.CountDownLatch) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Subscription(rx.Subscription) Test(org.junit.Test)

Example 95 with Action0

use of rx.functions.Action0 in project Hystrix by Netflix.

the class HystrixCommandTest method testEarlyUnsubscribeDuringFallback.

@Test
public void testEarlyUnsubscribeDuringFallback() {
    class AsyncCommand extends HystrixCommand<Boolean> {

        public AsyncCommand() {
            super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ASYNC")));
        }

        @Override
        protected Boolean run() {
            throw new RuntimeException("run failure");
        }

        @Override
        protected Boolean getFallback() {
            try {
                Thread.sleep(500);
                return false;
            } catch (InterruptedException ex) {
                throw new RuntimeException(ex);
            }
        }
    }
    HystrixCommand<Boolean> cmd = new AsyncCommand();
    final CountDownLatch latch = new CountDownLatch(1);
    Observable<Boolean> o = cmd.toObservable();
    Subscription s = o.doOnUnsubscribe(new Action0() {

        @Override
        public void call() {
            System.out.println("OnUnsubscribe");
            latch.countDown();
        }
    }).subscribe(new Subscriber<Boolean>() {

        @Override
        public void onCompleted() {
            System.out.println("OnCompleted");
            latch.countDown();
        }

        @Override
        public void onError(Throwable e) {
            System.out.println("OnError : " + e);
        }

        @Override
        public void onNext(Boolean b) {
            System.out.println("OnNext : " + b);
        }
    });
    try {
        // give fallback a chance to fire
        Thread.sleep(10);
        s.unsubscribe();
        assertTrue(latch.await(200, TimeUnit.MILLISECONDS));
        assertEquals("Number of execution semaphores in use", 0, cmd.getExecutionSemaphore().getNumberOfPermitsUsed());
        assertEquals("Number of fallback semaphores in use", 0, cmd.getFallbackSemaphore().getNumberOfPermitsUsed());
        assertEquals(0, cmd.metrics.getCurrentConcurrentExecutionCount());
        assertFalse(cmd.isExecutionComplete());
    } catch (InterruptedException ex) {
        ex.printStackTrace();
    }
}
Also used : Action0(rx.functions.Action0) CountDownLatch(java.util.concurrent.CountDownLatch) HystrixRuntimeException(com.netflix.hystrix.exception.HystrixRuntimeException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Subscription(rx.Subscription) Test(org.junit.Test)

Aggregations

Action0 (rx.functions.Action0)134 Subscription (rx.Subscription)58 Test (org.junit.Test)56 CountDownLatch (java.util.concurrent.CountDownLatch)50 Action1 (rx.functions.Action1)28 AtomicReference (java.util.concurrent.atomic.AtomicReference)23 ArrayList (java.util.ArrayList)16 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)16 List (java.util.List)15 Func1 (rx.functions.Func1)13 HystrixRuntimeException (com.netflix.hystrix.exception.HystrixRuntimeException)12 Observable (rx.Observable)12 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)11 OnClick (butterknife.OnClick)10 IOException (java.io.IOException)9 CommandStreamTest (com.netflix.hystrix.metric.CommandStreamTest)8 UiThreadTest (android.support.test.annotation.UiThreadTest)7 PluginTestVerifier (com.navercorp.pinpoint.bootstrap.plugin.test.PluginTestVerifier)7 TestCollapserTimer (com.netflix.hystrix.HystrixCollapserTest.TestCollapserTimer)7 Method (java.lang.reflect.Method)7