在实际业务中,交易都是由多个上游组成的,一般成功的数据组织能够满足我们设计的要求,但是如果其中某个环节出了异常,在最终的下游很难捕获到哪里出了错误,尤其是需要在异常中添加一些业务信息与埋点功能相合作,完成线上问题排查,特此通过研究retryWhen操作符号源码,通代理模式,将异常进行统一封装处理,已满足这个场景的要求。
// 封装一个业务需要的异常类,采用静态代理(装饰模式)扩展原异常
class BizThrowableExt(cause: Throwable?): Throwable(cause) {
// 业务相关数据,也可以通过继承,组合等模式形成复杂的业务属性
var url:String = ""
var code:String = ""
var msg:String = ""
}
异常处理源码,实现Function,在内部通过flatMap操作,对上游传递下来的异常进行封装处理,最后通过 Observable.error 将异常再往下游传递。
import io.reactivex.Observable
import io.reactivex.ObservableSource
import io.reactivex.functions.Function
class ThrowableTransform(private val url:String, private var code:String="", private var msg:String=""):Function,ObservableSource> {
override fun apply(attempts: Observable): ObservableSource {
return attempts.flatMap {
Observable.error(transform(it,url, code, msg))
}
}
private fun transform(original:Throwable, url:String, code:String, msg:String):Throwable{
return BizThrowableExt(original).apply {
this.url = url
this.msg = msg
this.code = code
}
}
}
业务源码通模式登录和获取token 相关业务,在发生异常时,将业务相关信息,传递到下游,下游可以根据异常,获取到业务信息,和原始的异常。
private fun test2(){
Observable.zip(observableLogin(),observableToken()) { userInfo, token ->
println(" userInfo== $userInfo,token == $token")
userInfo + token
}.observeOn(AndroidSchedulers.mainThread())
.subscribe ({
println("${Thread.currentThread().id} resutl == $it")
},{
if(it is BizThrowableExt){
println("url == ${it.url}")
}
})
}
// 模拟登录相关业务
private fun observableLogin(): Observable {
return Observable.create(ObservableOnSubscribe { e: ObservableEmitter ->
println("observableLogin thread id ${Thread.currentThread().id}")
Thread.sleep(3000)
e.onNext("user login")
e.onError(RuntimeException())
e.onComplete()
}).subscribeOn(Schedulers.io())
.retryWhen(ThrowableTransform("loginUrl","登录相关错误","登录相关信息"))
}
private fun observableToken(): Observable {
val data1 = "发起token其他信息"
return Observable.create(ObservableOnSubscribe { e: ObservableEmitter ->
try{
println("observableToken thread id ${Thread.currentThread().id}")
Thread.sleep(5000)
e.onNext("user token")
e.onComplete()
}catch (e:Exception){
//throw e
}
}).subscribeOn(Schedulers.io())
.retryWhen(ThrowableTransform("tokeUrl","token相关错误",data1))
}
名称定义:
Observable.create { e: ObservableEmitter ->
e.onNext("A")
e.onComplete()
}.retryWhen { attempts->
var count = 0;
attempts.flatMap { throwable ->
if(count < 3){
Observable.just("just retry!")
}else{
Observable.error(throwable)
}
}
}.subscribe {
println("result $it")
}
调用入口
public final Observable retryWhen(
final Function super Observable, ? extends ObservableSource>> handler) {
ObjectHelper.requireNonNull(handler, "handler is null");
// 将retryWhen的上游(例子中是用Observable.create 创建出的上游)和 处理异常构建的上游 通过 ObservableRetryWhen 返回一个新的上游,带异常处理的上游
// 可以简单的认为 在参数1 中 添加了一个参数2 的功能
return RxJavaPlugins.onAssembly(new ObservableRetryWhen(this, handler));
}
实现原理即rertyWhen源码
public final class ObservableRetryWhen extends AbstractObservableWithUpstream{
final Function super Observable, ? extends ObservableSource>> handler;
public ObservableRetryWhen(ObservableSource source, Function super Observable, ? extends ObservableSource>> handler) {
// 保存原上游
super(source);
this.handler = handler;
}
@Override
protected void subscribeActual(Observer super T> observer) {
// 构建一个新的Subject ,接受订阅后的异常
Subject signaller = PublishSubject.create().toSerialized();
ObservableSource> other;
try {
other = ObjectHelper.requireNonNull(handler.apply(signaller), "The handler returned a null ObservableSource");
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
EmptyDisposable.error(ex, observer);
return;
}
// 将上游和下游,和异常处理器封装起来
// 注意 RepeatWhenObserver 也是 Observer
// RepeatWhenObserver 在 订阅关系发生时,是先调用到RepeatWhenObserver
// RepeatWhenObserver 根据接受到的数据,在合适的机会给下游传递
RepeatWhenObserver parent = new RepeatWhenObserver(observer, signaller, source);
observer.onSubscribe(parent);
// other(内部有signaller) 和 parent.inner 形成订阅关系
other.subscribe(parent.inner);
// 将原上游和RepeatWhenObserver 形成订阅关系
parent.subscribeNext();
}
}
RepeatWhenObserver 源码如下
static final class RepeatWhenObserver extends AtomicInteger implements Observer, Disposable {
private static final long serialVersionUID = 802743776666017014L;
final Observer super T> downstream;
final AtomicInteger wip;
final AtomicThrowable error;
final Subject signaller;
final InnerRepeatObserver inner;
final AtomicReference upstream;
final ObservableSource source;
volatile boolean active;
RepeatWhenObserver(Observer super T> actual, Subject signaller, ObservableSource source) {
this.downstream = actual;
this.signaller = signaller;
this.source = source;
this.wip = new AtomicInteger();
this.error = new AtomicThrowable();
this.inner = new InnerRepeatObserver();
this.upstream = new AtomicReference();
}
@Override
public void onSubscribe(Disposable d) {
// 将原下游替换为 RepeatWhenObserver
DisposableHelper.replace(this.upstream, d);
}
@Override
public void onNext(T t) {
// 调用原下游继续传递onNext事件
HalfSerializer.onNext(downstream, t, this, error);
}
@Override
public void onError(Throwable e) {
DisposableHelper.replace(upstream, null);
active = false;
// 通过 signaller 转到 inner 中处理,将throwable 事件转换为 onNext事件
signaller.onNext(e);
}
@Override
public void onComplete() {
// 取消相关处理,包括 inner
DisposableHelper.dispose(inner);
// 调用原下游downstream 的onComplete
HalfSerializer.onComplete(downstream, this, error);
}
@Override
public boolean isDisposed() {
return DisposableHelper.isDisposed(upstream.get());
}
@Override
public void dispose() {
DisposableHelper.dispose(upstream);
DisposableHelper.dispose(inner);
}
void innerNext() {
// 重新将原上游和 RepeatWhenObserver 形成订阅关系
subscribeNext();
}
void innerError(Throwable ex) {
DisposableHelper.dispose(upstream);
// 直接调用原上游的onError
HalfSerializer.onError(downstream, ex, this, error);
}
void innerComplete() {
DisposableHelper.dispose(upstream);
HalfSerializer.onComplete(downstream, this, error);
}
void subscribeNext() {
if (wip.getAndIncrement() == 0) {
do {
if (isDisposed()) {
return;
}
if (!active) {
active = true;
source.subscribe(this);
}
} while (wip.decrementAndGet() != 0);
}
}
// 当原上游 出现异常时候,在 InnerRepeatObserver 处理
final class InnerRepeatObserver extends AtomicReference implements Observer