Tatsuya Fujisaki
Tatsuya Fujisaki

Reputation: 2001

RxJava's retryWhen unexpectedly keeps retrying forever

Can anyone …

  1. explain why the following code keeps retrying indefinitely, once retryWhen is called?
  2. correct the code to stop retrying when Random.nextBoolean() returns true?

I think there is a 50% chance that retryWhen is called because of Random.nextBoolean(). However, once it is called, it goes into an infinite loop.

import io.reactivex.rxjava3.core.Observable
import kotlin.random.Random

fun main() {
    Observable
        .just(Unit)
        .flatMap {
            if (Random.nextBoolean()) {
                Observable.just(Unit)
            } else {
                Observable.error(Throwable())
            }.retryWhen {
                it.flatMap {
                    println("retryWhen")
                    Observable.just(Unit)
                }
            }
        }
        .subscribe()
}

Output:

retryWhen
retryWhen
retryWhen
⋮
(continued)

Upvotes: 0

Views: 333

Answers (2)

dung ta van
dung ta van

Reputation: 1026

Please take a look the same question and answer

Copied answer:

retryWhen calls the provided function when an Observer subscribes to it so you have a main sequence accompanied by a sequence that emits the Throwable the main sequence failed with. You should compose a logic onto the Observable you get in this Function so at the end, one Throwable will result in a value on the other end.

I think your expectation is:
Observable
            .just(Unit)
            .flatMap {
                if (Random.nextBoolean()) {
                    Observable.just(Unit)
                } else {
                    Observable.error(Throwable())
                }.retryWhen {
                    it.takeWhile {
                        Random.nextBoolean()
                    }
                        .doOnNext {
                            println("retryWhen")
                        }
                }
            }
            .subscribe()

Upvotes: 0

homerman
homerman

Reputation: 3579

  1. You've applied the retryWhen to the result of the execution of either branch of the if-statement.

  2. Chain the retryWhen operator to the stream produced by flatMap:

e.g.

Observable
  .just(Unit)
  .flatMap {
    if(Random.nextBoolean()) {
      Observable.just(Unit)
    } else {
      Observable.error(Throwable())
    }
  }
  .retryWhen {
      it.flatMap {
        println("retryWhen")
        Observable.just(Unit)
      }
  }
  .subscribe()

Upvotes: 2

Related Questions