如何使用重试只有3次才放弃

时间:2018-07-01 10:32:03

标签: kotlin rx-java rx-java2

我想过滤某些上链函数在执行过程中何时发生特定异常,并尝试仅重试整个过程3次,如果仍然失败,则放弃。我来到了这样的地方:

   val disposable = someFunction(someParameter, delay, subject)
    .flatMapCompletable { (parameter1, parameter2) ->
      anotherFunction(parameter1, parameter2, subject)
    }
    .retryWhen { throwable ->
      throwable.filter {
        it.cause?.cause is ExampleException1
            || it.cause?.cause is ExampleException2
            || it.cause is ExampleException3
      }
    }
    .andThen(someStuff())
    .subscribe({
      Timber.d("Finished!")
    }, {
      Timber.d("Failed!")
    })

如何正确执行?

3 个答案:

答案 0 :(得分:3)

您可以将zipWithrange配合使用。

.retryWhen { errors -> errors.zipWith(Observable.range(1, 3), { _, i -> i }) }

retryWhen运算符为您提供了来自源发布者的所有错误流。在这里用数字1、2、3压缩它们。因此,结果流将发出3 next,后跟complete。与您可能会认为它只重新订阅两次相反,因为在第三个complete之后立即发出的next导致整个流完成。

您可以通过仅重试某些错误而又立即使其他错误失败来进一步扩展此范围。例如,如果您只想重试IOException,则可以将上述解决方案扩展到:

.retryWhen { errors -> errors
  .zipWith(Observable.range(1, 3), { error, _ -> error })
  .map { error -> when (error) {
    is IOException -> error
    else -> throw error
  }}
}

由于map在Java中无法引发检查异常,因此Java用户可以出于相同目的使用flatMap

答案 1 :(得分:1)

我认为您可以尝试完全通过retry来实现:

val observable = Observable.defer {
    System.out.println("someMethod called") 
    val result1 = 2 // some value from someMethod()
    Observable.just(result1)
}

observable.flatMap { result ->
    // another method is called here but let's omit it for the sake of simplicity and throw some exception
    System.out.println("someMethod2 called") 
    throw IllegalArgumentException("Exception someMethod2")
    Observable.just("Something that won't be executed anyways")
}.retry { times, throwable ->
            System.out.println("Attempt# " + times)
            // if this condition is true then the retry will occur
            times < 3 && throwable is IllegalArgumentException
        }.subscribe(
                { result -> System.out.println(result) },
                { throwable -> System.out.println(throwable.localizedMessage) })

输出:

  

someMethod称为

     

someMethod2称为

     

尝试#1

     

someMethod称为

     

someMethod2称为

     

尝试#2

     

someMethod称为

     

someMethod2称为

     

尝试#3

     

Exception someMethod2

由于someMethod2总是抛出Exception,因此在观察者的Exception someMethod2中打印了3次onError

答案 2 :(得分:0)

具有指数延迟的代码:

    YourSingle()
        .retryWhen { errors: Flowable<Throwable> ->
           errors.zipWith(
              Flowable.range(1, retryLimit + 1),
              BiFunction<Throwable, Int, Int> { error: Throwable, retryCount: Int ->
                if (error is RightTypeOfException && retryCount < retryLimit) {
                    retryCount
                } else {
                    throw error
                }
            }
        ).flatMap { retryCount ->
            //exponential 1, 2, 4
            val delay = 2.toDouble().pow(retryCount.toDouble()).toLong() / 2
            Flowable.timer(delay, TimeUnit.SECONDS)
        }
    }
相关问题