Skip to content

Instantly share code, notes, and snippets.

@ZacSweers
Forked from jerrellmardis/ExponentialBackoff
Last active April 14, 2020 06:51
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ZacSweers/7902e3a0286774630f4f to your computer and use it in GitHub Desktop.
Save ZacSweers/7902e3a0286774630f4f to your computer and use it in GitHub Desktop.
Exponential Backoff using Rx.retryWhen() I DON'T KNOW WHY THIS HAS HIGH SEO I JUST FORKED IT TO SAVE A COPY
// retries up to 3 times while exponentially backing off with each retry
.retryWhen(errors ->
errors
.zipWith(
Observable.range(1, MAX_RETRIES), (n, i) -> i
)
.flatMap(
retryCount -> Observable.timer((long) Math.pow(4, retryCount), TimeUnit.SECONDS)
)
)
@trajakovic
Copy link

Since this was high result on google for Rx retryWhen exponential backoff, this implementation is slightly wrong.

By wrong I mean that this logic will never return error, even if MAX_RETRIES are exhausted.

So, if you put this on test:
Observable.throw(new Exception("Exception")).retryWhen(.....).subscribe() will finish without error.

@azatmar
Copy link

azatmar commented Jul 14, 2017

@trajakovic that is correct, you just need to use doOnError because the error is handled silently because of retry.
Something like this: doOnError(throwable ->Timber.e(throwable, "Blablabla Error has been occurred"))

For me it is more interesting, that the timer is not happening anymore, but the statement in retryWhen gets called obviously.

@phanmn
Copy link

phanmn commented Jul 22, 2017

@trajakovic you can try this

// retries up to 3 times while exponentially backing off with each retry
                .retryWhen(errors ->
                       errors
                          .scan((errCount, err) -> {
                             if (errCount > MAX_RETRIES)
                               throw err;

                             return errCount + 1;
                           }, 0)
                           .flatMap(
                                   retryCount -> Observable.timer((long) Math.pow(4, retryCount), TimeUnit.SECONDS)
                           )
                                
                )

@FAMM2017
Copy link

FAMM2017 commented Aug 3, 2017

You guys should try something like this, the example retry 3 times(With a delay of one second) after this return the error:

static final int retrycount=4;

///...
.retryWhen(errors->errors
.zipWith(Observable.range(1,retrycount),(err,attempt)->
attempt<retrycount?
Observable.timer(1,TimeUnit.SECONDS):
Observable.error(err))
.flatMap(x->x)
)

//Tested and running at 100%

@tuchangwei
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment