Search in sources :

Example 1 with Func0

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

the class AbstractCommand method toObservable.

/**
     * Used for asynchronous execution of command with a callback by subscribing to the {@link Observable}.
     * <p>
     * This lazily starts execution of the command once the {@link Observable} is subscribed to.
     * <p>
     * An eager {@link Observable} can be obtained from {@link #observe()}.
     * <p>
     * See https://github.com/ReactiveX/RxJava/wiki for more information.
     * 
     * @return {@code Observable<R>} that executes and calls back with the result of command execution or a fallback if the command fails for any reason.
     * @throws HystrixRuntimeException
     *             if a fallback does not exist
     *             <p>
     *             <ul>
     *             <li>via {@code Observer#onError} if a failure occurs</li>
     *             <li>or immediately if the command can not be queued (such as short-circuited, thread-pool/semaphore rejected)</li>
     *             </ul>
     * @throws HystrixBadRequestException
     *             via {@code Observer#onError} if invalid arguments or state were used representing a user failure, not a system failure
     * @throws IllegalStateException
     *             if invoked more than once
     */
public Observable<R> toObservable() {
    final AbstractCommand<R> _cmd = this;
    //doOnCompleted handler already did all of the SUCCESS work
    //doOnError handler already did all of the FAILURE/TIMEOUT/REJECTION/BAD_REQUEST work
    final Action0 terminateCommandCleanup = new Action0() {

        @Override
        public void call() {
            if (_cmd.commandState.compareAndSet(CommandState.OBSERVABLE_CHAIN_CREATED, CommandState.TERMINAL)) {
                //user code never ran
                handleCommandEnd(false);
            } else if (_cmd.commandState.compareAndSet(CommandState.USER_CODE_EXECUTED, CommandState.TERMINAL)) {
                //user code did run
                handleCommandEnd(true);
            }
        }
    };
    //mark the command as CANCELLED and store the latency (in addition to standard cleanup)
    final Action0 unsubscribeCommandCleanup = new Action0() {

        @Override
        public void call() {
            if (_cmd.commandState.compareAndSet(CommandState.OBSERVABLE_CHAIN_CREATED, CommandState.UNSUBSCRIBED)) {
                if (!_cmd.executionResult.containsTerminalEvent()) {
                    _cmd.eventNotifier.markEvent(HystrixEventType.CANCELLED, _cmd.commandKey);
                    try {
                        executionHook.onUnsubscribe(_cmd);
                    } catch (Throwable hookEx) {
                        logger.warn("Error calling HystrixCommandExecutionHook.onUnsubscribe", hookEx);
                    }
                    _cmd.executionResultAtTimeOfCancellation = _cmd.executionResult.addEvent((int) (System.currentTimeMillis() - _cmd.commandStartTimestamp), HystrixEventType.CANCELLED);
                }
                //user code never ran
                handleCommandEnd(false);
            } else if (_cmd.commandState.compareAndSet(CommandState.USER_CODE_EXECUTED, CommandState.UNSUBSCRIBED)) {
                if (!_cmd.executionResult.containsTerminalEvent()) {
                    _cmd.eventNotifier.markEvent(HystrixEventType.CANCELLED, _cmd.commandKey);
                    try {
                        executionHook.onUnsubscribe(_cmd);
                    } catch (Throwable hookEx) {
                        logger.warn("Error calling HystrixCommandExecutionHook.onUnsubscribe", hookEx);
                    }
                    _cmd.executionResultAtTimeOfCancellation = _cmd.executionResult.addEvent((int) (System.currentTimeMillis() - _cmd.commandStartTimestamp), HystrixEventType.CANCELLED);
                }
                //user code did run
                handleCommandEnd(true);
            }
        }
    };
    final Func0<Observable<R>> applyHystrixSemantics = new Func0<Observable<R>>() {

        @Override
        public Observable<R> call() {
            if (commandState.get().equals(CommandState.UNSUBSCRIBED)) {
                return Observable.never();
            }
            return applyHystrixSemantics(_cmd);
        }
    };
    final Func1<R, R> wrapWithAllOnNextHooks = new Func1<R, R>() {

        @Override
        public R call(R r) {
            R afterFirstApplication = r;
            try {
                afterFirstApplication = executionHook.onComplete(_cmd, r);
            } catch (Throwable hookEx) {
                logger.warn("Error calling HystrixCommandExecutionHook.onComplete", hookEx);
            }
            try {
                return executionHook.onEmit(_cmd, afterFirstApplication);
            } catch (Throwable hookEx) {
                logger.warn("Error calling HystrixCommandExecutionHook.onEmit", hookEx);
                return afterFirstApplication;
            }
        }
    };
    final Action0 fireOnCompletedHook = new Action0() {

        @Override
        public void call() {
            try {
                executionHook.onSuccess(_cmd);
            } catch (Throwable hookEx) {
                logger.warn("Error calling HystrixCommandExecutionHook.onSuccess", hookEx);
            }
        }
    };
    return Observable.defer(new Func0<Observable<R>>() {

        @Override
        public Observable<R> call() {
            /* this is a stateful object so can only be used once */
            if (!commandState.compareAndSet(CommandState.NOT_STARTED, CommandState.OBSERVABLE_CHAIN_CREATED)) {
                IllegalStateException ex = new IllegalStateException("This instance can only be executed once. Please instantiate a new instance.");
                //TODO make a new error type for this
                throw new HystrixRuntimeException(FailureType.BAD_REQUEST_EXCEPTION, _cmd.getClass(), getLogMessagePrefix() + " command executed multiple times - this is not permitted.", ex, null);
            }
            commandStartTimestamp = System.currentTimeMillis();
            if (properties.requestLogEnabled().get()) {
                // log this command execution regardless of what happened
                if (currentRequestLog != null) {
                    currentRequestLog.addExecutedCommand(_cmd);
                }
            }
            final boolean requestCacheEnabled = isRequestCachingEnabled();
            final String cacheKey = getCacheKey();
            /* try from cache first */
            if (requestCacheEnabled) {
                HystrixCommandResponseFromCache<R> fromCache = (HystrixCommandResponseFromCache<R>) requestCache.get(cacheKey);
                if (fromCache != null) {
                    isResponseFromCache = true;
                    return handleRequestCacheHitAndEmitValues(fromCache, _cmd);
                }
            }
            Observable<R> hystrixObservable = Observable.defer(applyHystrixSemantics).map(wrapWithAllOnNextHooks);
            Observable<R> afterCache;
            // put in cache
            if (requestCacheEnabled && cacheKey != null) {
                // wrap it for caching
                HystrixCachedObservable<R> toCache = HystrixCachedObservable.from(hystrixObservable, _cmd);
                HystrixCommandResponseFromCache<R> fromCache = (HystrixCommandResponseFromCache<R>) requestCache.putIfAbsent(cacheKey, toCache);
                if (fromCache != null) {
                    // another thread beat us so we'll use the cached value instead
                    toCache.unsubscribe();
                    isResponseFromCache = true;
                    return handleRequestCacheHitAndEmitValues(fromCache, _cmd);
                } else {
                    // we just created an ObservableCommand so we cast and return it
                    afterCache = toCache.toObservable();
                }
            } else {
                afterCache = hystrixObservable;
            }
            return afterCache.doOnTerminate(// perform cleanup once (either on normal terminal state (this line), or unsubscribe (next line))
            terminateCommandCleanup).doOnUnsubscribe(// perform cleanup once
            unsubscribeCommandCleanup).doOnCompleted(fireOnCompletedHook);
        }
    });
}
Also used : Action0(rx.functions.Action0) HystrixRuntimeException(com.netflix.hystrix.exception.HystrixRuntimeException) Observable(rx.Observable) Func1(rx.functions.Func1) Func0(rx.functions.Func0)

Example 2 with Func0

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

the class HystrixObservableCommandTest method testRequestContextOnRejectionWithFallback.

private RequestContextTestResults testRequestContextOnRejectionWithFallback(ExecutionIsolationStrategy isolation, final Scheduler userScheduler) {
    final RequestContextTestResults results = new RequestContextTestResults();
    TestHystrixObservableCommand<Boolean> command = new TestHystrixObservableCommand<Boolean>(TestHystrixObservableCommand.testPropsBuilder(new TestCircuitBreaker()).setCommandPropertiesDefaults(HystrixCommandPropertiesTest.getUnitTestPropertiesSetter().withExecutionIsolationStrategy(isolation).withExecutionIsolationSemaphoreMaxConcurrentRequests(0)).setThreadPool(new HystrixThreadPool() {

        @Override
        public ThreadPoolExecutor getExecutor() {
            return null;
        }

        @Override
        public void markThreadExecution() {
        }

        @Override
        public void markThreadCompletion() {
        }

        @Override
        public void markThreadRejection() {
        }

        @Override
        public boolean isQueueSpaceAvailable() {
            // always return false so we reject everything
            return false;
        }

        @Override
        public Scheduler getScheduler() {
            return new HystrixContextScheduler(HystrixPlugins.getInstance().getConcurrencyStrategy(), this);
        }

        @Override
        public Scheduler getScheduler(Func0<Boolean> shouldInterruptThread) {
            return new HystrixContextScheduler(HystrixPlugins.getInstance().getConcurrencyStrategy(), this, shouldInterruptThread);
        }
    })) {

        @Override
        protected Observable<Boolean> construct() {
            return Observable.create(new OnSubscribe<Boolean>() {

                @Override
                public void call(Subscriber<? super Boolean> s) {
                    s.onError(new RuntimeException("onError"));
                }
            }).subscribeOn(userScheduler);
        }

        @Override
        protected Observable<Boolean> resumeWithFallback() {
            return Observable.create(new OnSubscribe<Boolean>() {

                @Override
                public void call(Subscriber<? super Boolean> s) {
                    results.isContextInitialized.set(HystrixRequestContext.isCurrentThreadInitialized());
                    results.originThread.set(Thread.currentThread());
                    s.onNext(false);
                    s.onCompleted();
                }
            }).subscribeOn(userScheduler);
        }
    };
    results.command = command;
    command.toObservable().doOnEach(new Action1<Notification<? super Boolean>>() {

        @Override
        public void call(Notification<? super Boolean> n) {
            results.isContextInitializedObserveOn.set(HystrixRequestContext.isCurrentThreadInitialized());
            results.observeOnThread.set(Thread.currentThread());
        }
    }).subscribe(results.ts);
    results.ts.awaitTerminalEvent();
    System.out.println("Run => Initialized: " + results.isContextInitialized.get() + "  Thread: " + results.originThread.get());
    System.out.println("Observed => Initialized: " + results.isContextInitializedObserveOn.get() + "  Thread: " + results.observeOnThread.get());
    assertEquals(0, results.ts.getOnErrorEvents().size());
    assertEquals(1, results.ts.getOnNextEvents().size());
    assertEquals(false, results.ts.getOnNextEvents().get(0));
    assertFalse(command.isSuccessfulExecution());
    assertTrue(command.isResponseRejected());
    if (isolation == ExecutionIsolationStrategy.SEMAPHORE) {
        assertCommandExecutionEvents(command, HystrixEventType.SEMAPHORE_REJECTED, HystrixEventType.FALLBACK_EMIT, HystrixEventType.FALLBACK_SUCCESS);
    } else {
        assertCommandExecutionEvents(command, HystrixEventType.THREAD_POOL_REJECTED, HystrixEventType.FALLBACK_EMIT, HystrixEventType.FALLBACK_SUCCESS);
    }
    assertEquals(0, command.metrics.getCurrentConcurrentExecutionCount());
    assertSaneHystrixRequestLog(1);
    return results;
}
Also used : TestCircuitBreaker(com.netflix.hystrix.HystrixCircuitBreakerTest.TestCircuitBreaker) Action1(rx.functions.Action1) HystrixContextScheduler(com.netflix.hystrix.strategy.concurrency.HystrixContextScheduler) OnSubscribe(rx.Observable.OnSubscribe) Notification(rx.Notification) HystrixRuntimeException(com.netflix.hystrix.exception.HystrixRuntimeException) TestSubscriber(rx.observers.TestSubscriber) Subscriber(rx.Subscriber) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Func0(rx.functions.Func0)

Example 3 with Func0

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

the class HystrixObservableCommandTest method testEarlyUnsubscribeDuringExecutionViaToObservable.

@Test
public void testEarlyUnsubscribeDuringExecutionViaToObservable() {
    class AsyncCommand extends HystrixObservableCommand<Boolean> {

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

        @Override
        protected Observable<Boolean> construct() {
            return Observable.defer(new Func0<Observable<Boolean>>() {

                @Override
                public Observable<Boolean> call() {
                    try {
                        Thread.sleep(100);
                        return Observable.just(true);
                    } catch (InterruptedException ex) {
                        return Observable.error(ex);
                    }
                }
            }).subscribeOn(Schedulers.io());
        }
    }
    HystrixObservableCommand<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 {
        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());
        assertFalse(cmd.isExecutionComplete());
        assertFalse(cmd.isExecutedInThread());
        System.out.println("EventCounts : " + cmd.getEventCounts());
        System.out.println("Execution Time : " + cmd.getExecutionTimeInMilliseconds());
        System.out.println("Is Successful : " + cmd.isSuccessfulExecution());
    } 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) Func0(rx.functions.Func0) Test(org.junit.Test)

Example 4 with Func0

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

the class HystrixTest method testMultipleSemaphoreObservableCommandsInFlight.

//    @Test
//    public void testSemaphoreIsolatedAsynchronousHystrixObservableCommand() {
//        HystrixObservableCommand<Integer> observableCmd = new AsynchronousObservableCommand();
//
//        assertNull(Hystrix.getCurrentThreadExecutingCommand());
//
//        final CountDownLatch latch = new CountDownLatch(1);
//
//        observableCmd.observe().subscribe(new Subscriber<Integer>() {
//            @Override
//            public void onCompleted() {
//                latch.countDown();
//            }
//
//            @Override
//            public void onError(Throwable e) {
//                fail(e.getMessage());
//                latch.countDown();
//            }
//
//            @Override
//            public void onNext(Integer value) {
//                System.out.println(Thread.currentThread().getName() + " : " + System.currentTimeMillis() + " AsyncObservable latched Subscriber OnNext : " + value);
//            }
//        });
//
//        try {
//            assertNull(Hystrix.getCurrentThreadExecutingCommand());
//            assertEquals(0, Hystrix.getCommandCount());
//            latch.await();
//        } catch (InterruptedException ex) {
//            fail(ex.getMessage());
//        }
//
//        assertNull(Hystrix.getCurrentThreadExecutingCommand());
//        assertEquals(0, Hystrix.getCommandCount());
//    }
@Test
public void testMultipleSemaphoreObservableCommandsInFlight() throws InterruptedException {
    int NUM_COMMANDS = 50;
    List<Observable<Integer>> commands = new ArrayList<Observable<Integer>>();
    for (int i = 0; i < NUM_COMMANDS; i++) {
        commands.add(Observable.defer(new Func0<Observable<Integer>>() {

            @Override
            public Observable<Integer> call() {
                return new AsynchronousObservableCommand().observe();
            }
        }));
    }
    final AtomicBoolean exceptionFound = new AtomicBoolean(false);
    final CountDownLatch latch = new CountDownLatch(1);
    Observable.merge(commands).subscribe(new Subscriber<Integer>() {

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

        @Override
        public void onError(Throwable e) {
            System.out.println("OnError : " + e);
            e.printStackTrace();
            exceptionFound.set(true);
            latch.countDown();
        }

        @Override
        public void onNext(Integer n) {
            // + " : " + Hystrix.getCurrentThreadExecutingCommand().name() + " : " + Hystrix.getCommandCount());
            System.out.println("OnNext : " + n + " : " + Thread.currentThread().getName() + " : " + Hystrix.getCommandCount());
        }
    });
    latch.await();
    assertFalse(exceptionFound.get());
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ArrayList(java.util.ArrayList) CountDownLatch(java.util.concurrent.CountDownLatch) Func0(rx.functions.Func0) Observable(rx.Observable) Test(org.junit.Test)

Example 5 with Func0

use of rx.functions.Func0 in project mosby by sockeqwe.

the class MailProvider method getFilteredMailList.

/**
   * Filters the list of mails by the given criteria
   */
private Observable<List<Mail>> getFilteredMailList(Func1<Mail, Boolean> filterFnc, final boolean withDelayAndError) {
    return Observable.defer(new Func0<Observable<Mail>>() {

        @Override
        public Observable<Mail> call() {
            if (withDelayAndError) {
                delay();
                Observable o = checkExceptions();
                if (o != null) {
                    return o;
                }
            }
            return Observable.from(mails);
        }
    }).filter(filterFnc).collect(new Func0<List<Mail>>() {

        @Override
        public List<Mail> call() {
            return new ArrayList<Mail>();
        }
    }, new Action2<List<Mail>, Mail>() {

        @Override
        public void call(List<Mail> mails, Mail mail) {
            mails.add(mail);
        }
    }).map(new Func1<List<Mail>, List<Mail>>() {

        @Override
        public List<Mail> call(List<Mail> mails) {
            Collections.sort(mails, MailComparator.INSTANCE);
            return mails;
        }
    });
}
Also used : Action2(rx.functions.Action2) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) Func0(rx.functions.Func0) Observable(rx.Observable)

Aggregations

Func0 (rx.functions.Func0)9 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)5 Observable (rx.Observable)5 Action0 (rx.functions.Action0)5 HystrixRuntimeException (com.netflix.hystrix.exception.HystrixRuntimeException)4 CountDownLatch (java.util.concurrent.CountDownLatch)4 Test (org.junit.Test)4 Subscription (rx.Subscription)3 ArrayList (java.util.ArrayList)2 TestCircuitBreaker (com.netflix.hystrix.HystrixCircuitBreakerTest.TestCircuitBreaker)1 HystrixContextScheduler (com.netflix.hystrix.strategy.concurrency.HystrixContextScheduler)1 List (java.util.List)1 Notification (rx.Notification)1 OnSubscribe (rx.Observable.OnSubscribe)1 Subscriber (rx.Subscriber)1 Action1 (rx.functions.Action1)1 Action2 (rx.functions.Action2)1 Func1 (rx.functions.Func1)1 TestSubscriber (rx.observers.TestSubscriber)1