// store the command that is being run
endCurrentThreadExecutingCommand.set(Hystrix.startCurrentThreadExecutingCommand(getCommandKey()));
getRunObservableDecoratedForMetricsAndErrorHandling(performAsyncTimeout)
.doOnTerminate(new Action0() {
@Override
public void call() {
// release the semaphore
// this is done here instead of below so that the acquire/release happens where it is guaranteed
// and not affected by the conditional circuit-breaker checks, timeouts, etc
executionSemaphore.release();
}
}).unsafeSubscribe(observer);
} catch (RuntimeException e) {
observer.onError(e);
}
} else {
metrics.markSemaphoreRejection();
logger.debug("HystrixCommand Execution Rejection by Semaphore."); // debug only since we're throwing the exception and someone higher will do something with it
// retrieve a fallback or throw an exception if no fallback available
getFallbackOrThrowException(HystrixEventType.SEMAPHORE_REJECTED, FailureType.REJECTED_SEMAPHORE_EXECUTION, "could not acquire a semaphore for execution").unsafeSubscribe(observer);
}
} else {
// record that we are returning a short-circuited fallback
metrics.markShortCircuited();
// short-circuit and go directly to fallback (or throw an exception if no fallback implemented)
try {
getFallbackOrThrowException(HystrixEventType.SHORT_CIRCUITED, FailureType.SHORTCIRCUIT, "short-circuited").unsafeSubscribe(observer);
} catch (Exception e) {
observer.onError(e);
}
}
}
});
// error handling at very end (this means fallback didn't exist or failed)
o = o.onErrorResumeNext(new Func1<Throwable, Observable<R>>() {
@Override
public Observable<R> call(Throwable t) {
// count that we are throwing an exception and re-throw it
metrics.markExceptionThrown();
return Observable.error(t);
}
});
// any final cleanup needed
o = o.doOnTerminate(new Action0() {
@Override
public void call() {
Reference<TimerListener> tl = timeoutTimer.get();
if (tl != null) {