Search in sources :

Example 26 with Action0

use of rx.functions.Action0 in project realm-java by realm.

the class RxJavaTests method realmResults_closeInDoOnUnsubscribe.

@Test
@UiThreadTest
public void realmResults_closeInDoOnUnsubscribe() {
    Observable<RealmResults<AllTypes>> observable = realm.where(AllTypes.class).findAll().asObservable().doOnUnsubscribe(new Action0() {

        @Override
        public void call() {
            realm.close();
        }
    });
    subscription = observable.subscribe(new Action1<RealmResults<AllTypes>>() {

        @Override
        public void call(RealmResults<AllTypes> allTypes) {
        }
    });
    subscription.unsubscribe();
    assertTrue(realm.isClosed());
}
Also used : Action0(rx.functions.Action0) Action1(rx.functions.Action1) AllTypes(io.realm.entities.AllTypes) UiThreadTest(android.support.test.annotation.UiThreadTest) Test(org.junit.Test) UiThreadTest(android.support.test.annotation.UiThreadTest)

Example 27 with Action0

use of rx.functions.Action0 in project realm-java by realm.

the class RxJavaTests method dynamicRealm_closeInDoOnUnsubscribe.

@Test
@UiThreadTest
public void dynamicRealm_closeInDoOnUnsubscribe() {
    final DynamicRealm dynamicRealm = DynamicRealm.getInstance(realm.getConfiguration());
    Observable<DynamicRealm> observable = dynamicRealm.asObservable().doOnUnsubscribe(new Action0() {

        @Override
        public void call() {
            dynamicRealm.close();
        }
    });
    subscription = observable.subscribe(new Action1<DynamicRealm>() {

        @Override
        public void call(DynamicRealm rxRealm) {
        }
    });
    subscription.unsubscribe();
    assertTrue(dynamicRealm.isClosed());
}
Also used : Action0(rx.functions.Action0) Action1(rx.functions.Action1) UiThreadTest(android.support.test.annotation.UiThreadTest) Test(org.junit.Test) UiThreadTest(android.support.test.annotation.UiThreadTest)

Example 28 with Action0

use of rx.functions.Action0 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() {
            circuitBreaker.markNonSuccess();
            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 29 with Action0

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

the class AbstractCommand method observe.

/**
 * Used for asynchronous execution of command with a callback by subscribing to the {@link Observable}.
 * <p>
 * This eagerly starts execution of the command the same as {@link HystrixCommand#queue()} and {@link HystrixCommand#execute()}.
 * <p>
 * A lazy {@link Observable} can be obtained from {@link #toObservable()}.
 * <p>
 * See https://github.com/Netflix/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> observe() {
    // us a ReplaySubject to buffer the eagerly subscribed-to Observable
    ReplaySubject<R> subject = ReplaySubject.create();
    // eagerly kick off subscription
    final Subscription sourceSubscription = 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() {
            sourceSubscription.unsubscribe();
        }
    });
}
Also used : Action0(rx.functions.Action0) CompositeSubscription(rx.subscriptions.CompositeSubscription) Subscription(rx.Subscription)

Example 30 with Action0

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

the class AbstractCommand method getFallbackOrThrowException.

/**
 * Execute <code>getFallback()</code> within protection of a semaphore that limits number of concurrent executions.
 * <p>
 * Fallback implementations shouldn't perform anything that can be blocking, but we protect against it anyways in case someone doesn't abide by the contract.
 * <p>
 * If something in the <code>getFallback()</code> implementation is latent (such as a network call) then the semaphore will cause us to start rejecting requests rather than allowing potentially
 * all threads to pile up and block.
 *
 * @return K
 * @throws UnsupportedOperationException
 *             if getFallback() not implemented
 * @throws HystrixRuntimeException
 *             if getFallback() fails (throws an Exception) or is rejected by the semaphore
 */
private Observable<R> getFallbackOrThrowException(final AbstractCommand<R> _cmd, final HystrixEventType eventType, final FailureType failureType, final String message, final Exception originalException) {
    final HystrixRequestContext requestContext = HystrixRequestContext.getContextForCurrentThread();
    long latency = System.currentTimeMillis() - executionResult.getStartTimestamp();
    // record the executionResult
    // do this before executing fallback so it can be queried from within getFallback (see See https://github.com/Netflix/Hystrix/pull/144)
    executionResult = executionResult.addEvent((int) latency, eventType);
    if (isUnrecoverable(originalException)) {
        logger.error("Unrecoverable Error for HystrixCommand so will throw HystrixRuntimeException and not apply fallback. ", originalException);
        /* executionHook for all errors */
        Exception e = wrapWithOnErrorHook(failureType, originalException);
        return Observable.error(new HystrixRuntimeException(failureType, this.getClass(), getLogMessagePrefix() + " " + message + " and encountered unrecoverable error.", e, null));
    } else {
        if (isRecoverableError(originalException)) {
            logger.warn("Recovered from java.lang.Error by serving Hystrix fallback", originalException);
        }
        if (properties.fallbackEnabled().get()) {
            /* fallback behavior is permitted so attempt */
            final Action1<Notification<? super R>> setRequestContext = new Action1<Notification<? super R>>() {

                @Override
                public void call(Notification<? super R> rNotification) {
                    setRequestContextIfNeeded(requestContext);
                }
            };
            final Action1<R> markFallbackEmit = new Action1<R>() {

                @Override
                public void call(R r) {
                    if (shouldOutputOnNextEvents()) {
                        executionResult = executionResult.addEvent(HystrixEventType.FALLBACK_EMIT);
                        eventNotifier.markEvent(HystrixEventType.FALLBACK_EMIT, commandKey);
                    }
                }
            };
            final Action0 markFallbackCompleted = new Action0() {

                @Override
                public void call() {
                    long latency = System.currentTimeMillis() - executionResult.getStartTimestamp();
                    eventNotifier.markEvent(HystrixEventType.FALLBACK_SUCCESS, commandKey);
                    executionResult = executionResult.addEvent((int) latency, HystrixEventType.FALLBACK_SUCCESS);
                }
            };
            final Func1<Throwable, Observable<R>> handleFallbackError = new Func1<Throwable, Observable<R>>() {

                @Override
                public Observable<R> call(Throwable t) {
                    /* executionHook for all errors */
                    Exception e = wrapWithOnErrorHook(failureType, originalException);
                    Exception fe = getExceptionFromThrowable(t);
                    long latency = System.currentTimeMillis() - executionResult.getStartTimestamp();
                    Exception toEmit;
                    if (fe instanceof UnsupportedOperationException) {
                        // debug only since we're throwing the exception and someone higher will do something with it
                        logger.debug("No fallback for HystrixCommand. ", fe);
                        eventNotifier.markEvent(HystrixEventType.FALLBACK_MISSING, commandKey);
                        executionResult = executionResult.addEvent((int) latency, HystrixEventType.FALLBACK_MISSING);
                        toEmit = new HystrixRuntimeException(failureType, _cmd.getClass(), getLogMessagePrefix() + " " + message + " and no fallback available.", e, fe);
                    } else {
                        logger.debug("HystrixCommand execution " + failureType.name() + " and fallback failed.", fe);
                        eventNotifier.markEvent(HystrixEventType.FALLBACK_FAILURE, commandKey);
                        executionResult = executionResult.addEvent((int) latency, HystrixEventType.FALLBACK_FAILURE);
                        toEmit = new HystrixRuntimeException(failureType, _cmd.getClass(), getLogMessagePrefix() + " " + message + " and fallback failed.", e, fe);
                    }
                    // NOTE: we're suppressing fallback exception here
                    if (shouldNotBeWrapped(originalException)) {
                        return Observable.error(e);
                    }
                    return Observable.error(toEmit);
                }
            };
            final TryableSemaphore fallbackSemaphore = getFallbackSemaphore();
            final AtomicBoolean semaphoreHasBeenReleased = new AtomicBoolean(false);
            final Action0 singleSemaphoreRelease = new Action0() {

                @Override
                public void call() {
                    if (semaphoreHasBeenReleased.compareAndSet(false, true)) {
                        fallbackSemaphore.release();
                    }
                }
            };
            Observable<R> fallbackExecutionChain;
            // acquire a permit
            if (fallbackSemaphore.tryAcquire()) {
                try {
                    if (isFallbackUserDefined()) {
                        executionHook.onFallbackStart(this);
                        fallbackExecutionChain = getFallbackObservable();
                    } else {
                        // same logic as above without the hook invocation
                        fallbackExecutionChain = getFallbackObservable();
                    }
                } catch (Throwable ex) {
                    // If hook or user-fallback throws, then use that as the result of the fallback lookup
                    fallbackExecutionChain = Observable.error(ex);
                }
                return fallbackExecutionChain.doOnEach(setRequestContext).lift(new FallbackHookApplication(_cmd)).lift(new DeprecatedOnFallbackHookApplication(_cmd)).doOnNext(markFallbackEmit).doOnCompleted(markFallbackCompleted).onErrorResumeNext(handleFallbackError).doOnTerminate(singleSemaphoreRelease).doOnUnsubscribe(singleSemaphoreRelease);
            } else {
                return handleFallbackRejectionByEmittingError();
            }
        } else {
            return handleFallbackDisabledByEmittingError(originalException, failureType, message);
        }
    }
}
Also used : Action0(rx.functions.Action0) Action1(rx.functions.Action1) HystrixRuntimeException(com.netflix.hystrix.exception.HystrixRuntimeException) 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) Notification(rx.Notification) Observable(rx.Observable) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HystrixRequestContext(com.netflix.hystrix.strategy.concurrency.HystrixRequestContext) Func1(rx.functions.Func1)

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