RX Java - 重试一些抛出异常的代码

时间:2017-03-06 10:20:13

标签: java error-handling rx-java observable exponential-backoff

我正在尝试使用RX Java来消耗来自持续发送对象的源的一些数据。

我想知道如何为我自己的代码抛出异常的情况实现重试策略。例如,网络异常应该使用指数退避策略触发重试。

一些代码:

        Trimester I
        ABC
        Trimester II
        CDF
        Trimester III
        FGH
        Trimester IV
        XYZ
        Trimester I
        PQR
        FGH
        Trimester II
        MNO

message.map(this::processMessage) .subscribe((message)->{ //do something after mapping }); 是包含可能失败的风险代码的方法,以及我想要重试的代码部分,但我不想阻止observable从源代码中消耗数据。

对此有何想法?

3 个答案:

答案 0 :(得分:2)

message
    .map(this::processMessage)
    .retryWhen(errors -> errors.flatMap(error -> {  
        if (error instanceof IOException) {
          return Observable.just(null);
        }
        // For anything else, don't retry
        return Observable.error(error);
     })
     subscribe(
         System.out::println,
         error -> System.out.println("Error!")
     );

或捕获错误

message.map(this::processMessage)
           .onErrorReturn(error -> "Empty result")
           .subscribe((message)->{})

或发出错误

message
    .map(this::processMessage)
    .doOnError(throwable -> Log.e(TAG, "Throwable " + throwable.getMessage()))
    .subscribe(
         System.out::println,
         error -> System.out.println("Error!")
     );

未经测试,但重试时不同于重复时不仅在onComplete中调用。

http://blog.danlew.net/2016/01/25/rxjavas-repeatwhen-and-retrywhen-explained/ - >每个错误都是flatmapped,以便我们可以返回onNext(null)(触发重新订阅)或onError(错误)(以避免重新订阅)。

退避政策:

source.retryWhen(errors ->  
  errors
    .zipWith(Observable.range(1, 3), (n, i) -> i)
    .flatMap(retryCount -> Observable.timer((long) Math.pow(5, retryCount), TimeUnit.SECONDS))
);
在这种情况下,

flatMap + timer优于延迟,因为它允许我们通过重试次数来修改延迟。以上重试三次,并将每次重试延迟5 ^ retryCount,只需少量操作符即可实现指数退避!

答案 1 :(得分:1)

答案 2 :(得分:0)

最近我开发了完全符合您需求的库。

RetrofitRxErrorHandler

如果将Exponential策略与backupObservable结合使用,您将获得预期的结果。