【问题标题】:RX Java - Retry some code that throws exceptionRX Java - 重试一些引发异常的代码
【发布时间】:2017-03-06 10:20:13
【问题描述】:

我正在尝试使用 RX Java 来使用来自不断发送对象的源的一些数据。

我想知道如何针对我自己的代码引发异常的情况实施重试策略。例如,网络异常应使用指数退避策略触发重试。

一些代码:

 message.map(this::processMessage)
                 .subscribe((message)->{
                     //do something after mapping
                 });

processMessage(message) 是包含可能失败的风险代码及其代码部分的方法,我想重试但我不想阻止 observable 使用源中的数据。

对此有什么想法吗?

【问题讨论】:

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


    【解决方案1】:
    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!")
         );
    

    未经测试,但 retryWhen 与 repeatWhen 不同,后者不仅在 onComplete 中调用。

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

    退避政策:

    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 比延迟更可取,因为它允许我们通过重试次数来修改延迟。上述重试 3 次,每次重试延迟 5 ^ retryCount,只需少量运算符即可为您提供指数退避!

    【讨论】:

    • 您的建议不包含任何重复失败代码的逻辑。此外,如果你使用 onErrorReturn,observable 将停止使用新值
    • 指数退避策略怎么样?
    • 已修改。应该解决你的问题。如果不只是评论,那么将提供一个工作代码。
    【解决方案2】:
    【解决方案3】:

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

    RetrofitRxErrorHandler

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

    【讨论】:

    • 很酷的项目,但我没有使用 Retrofit 或 http。我有来自 RabbitMQ 的持续提要,并且 observable 对此作出响应。
    • 因此代码可能是您要实现的目标的基础。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多