1: public Observable<R> toObservable(){
2: final AbstractCommand<R> _cmd = this;
3:
4: //doOnCompleted handler already did all of the SUCCESS work5: //doOnError handler already did all of the FAILURE/TIMEOUT/REJECTION/BAD_REQUEST work6: final Action0 terminateCommandCleanup = new Action0() {} // ... 省略7:
8: //mark the command as CANCELLED and store the latency (in addition to standard cleanup)9: final Action0 unsubscribeCommandCleanup = new Action0() {} // ... 省略10:
11: final Func0<Observable<R>> applyHystrixSemantics = new Func0<Observable<R>>() {
12: @Override13: public Observable<R> call(){
14: if (commandState.get().equals(CommandState.UNSUBSCRIBED)) {
15: return Observable.never();
16: }
17: return applyHystrixSemantics(_cmd);
18: }
19: };
20:
21: final Func1<R, R> wrapWithAllOnNextHooks = new Func1<R, R>() {} // ... 省略 22:
23: final Action0 fireOnCompletedHook = new Action0() {} // ... 省略 24:
25: return Observable.defer(new Func0<Observable<R>>() {
26: @Override27: public Observable<R> call(){
28: /* this is a stateful object so can only be used once */29: if (!commandState.compareAndSet(CommandState.NOT_STARTED, CommandState.OBSERVABLE_CHAIN_CREATED)) {
30: IllegalStateException ex = new IllegalStateException("This instance can only be executed once. Please instantiate a new instance.");
31: //TODO make a new error type for this32: thrownew HystrixRuntimeException(FailureType.BAD_REQUEST_EXCEPTION, _cmd.getClass(), getLogMessagePrefix() + " command executed multiple times - this is not permitted.", ex, null);
33: }
34:
35: // 命令开始时间戳36: commandStartTimestamp = System.currentTimeMillis();
37:
38: // TODO【2001】【打印日志】39: if (properties.requestLogEnabled().get()) {
40: // log this command execution regardless of what happened41: if (currentRequestLog != null) {
42: currentRequestLog.addExecutedCommand(_cmd);
43: }
44: }
45:
46: // 缓存开关、缓存KEY47: finalboolean requestCacheEnabled = isRequestCachingEnabled();
48: final String cacheKey = getCacheKey();
49:
50: // 优先从缓存中获取51: /* try from cache first */52: if (requestCacheEnabled) {
53: HystrixCommandResponseFromCache<R> fromCache = (HystrixCommandResponseFromCache<R>) requestCache.get(cacheKey);
54: if (fromCache != null) {
55: isResponseFromCache = true; // 标记 从缓存中结果56: return handleRequestCacheHitAndEmitValues(fromCache, _cmd);
57: }
58: }
59:
60: // 获得 执行命令Observable61: Observable<R> hystrixObservable =
62: Observable.defer(applyHystrixSemantics)
63: .map(wrapWithAllOnNextHooks);
64:
65: // 获得 缓存Observable66: Observable<R> afterCache;
67: // put in cache68: if (requestCacheEnabled && cacheKey != null) {
69: // wrap it for caching70: HystrixCachedObservable<R> toCache = HystrixCachedObservable.from(hystrixObservable, _cmd);
71: // 并发若不存在72: HystrixCommandResponseFromCache<R> fromCache = (HystrixCommandResponseFromCache<R>) requestCache.putIfAbsent(cacheKey, toCache);
73: if (fromCache != null) { // 添加失败74: // another thread beat us so we'll use the cached value instead75: toCache.unsubscribe();
76: isResponseFromCache = true; // 标记 从缓存中结果77: return handleRequestCacheHitAndEmitValues(fromCache, _cmd);
78: } else { // 添加成功79: // we just created an ObservableCommand so we cast and return it80: afterCache = toCache.toObservable();
81: }
82: } else {
83: afterCache = hystrixObservable;
84: }
85:
86: //87: return afterCache
88: .doOnTerminate(terminateCommandCleanup) // perform cleanup once (either on normal terminal state (this line), or unsubscribe (next line))89: .doOnUnsubscribe(unsubscribeCommandCleanup) // perform cleanup once90: .doOnCompleted(fireOnCompletedHook);
91: }
92: });
93: }