Skip to content

Instantly share code, notes, and snippets.

@mradzinski
Last active February 24, 2018 18:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mradzinski/9a398b57d797dfc43fda2462f78ba4d6 to your computer and use it in GitHub Desktop.
Save mradzinski/9a398b57d797dfc43fda2462f78ba4d6 to your computer and use it in GitHub Desktop.
RxJava2 Retry with exponential backoff, maximum amount of retries and evaluator
class ExponentialBackoffRetryHandler<T : Throwable>(private val maxRetries: Int = 3,
private val retryDelayMs: Long = 2500,
private val evaluator: (Throwable, Int) -> Boolean = { _, _ -> true }):
Function<Flowable<T>, Publisher<*>> {
companion object {
private const val TAG: String = "ExponentialRetryHandler"
}
private var retryCount: Int = 0
@Throws(Exception::class)
override fun apply(attempts: Flowable<T>): Publisher<*> {
return attempts
.concatMap { ex ->
retryCount++
val throwable = ex as Throwable
val shouldRetry = evaluator.invoke(throwable, retryCount)
if ((retryCount<= maxRetries) && shouldRetry) {
val delayMs = retryDelayMs * retryCount
Log.w(TAG, "Retrying... attempt #$retryCount will be executed in ${delayMs / 1000F} seconds")
return@concatMap Flowable.timer(delayMs, TimeUnit.MILLISECONDS)
}
return@concatMap Flowable.error<T>(throwable)
}
}
}
ApiClient.operation()
.retryWhen(ExponentialBackoffRetryHandler shouldRetry@{ ex, retryCount ->
// Evaluator will be invoked before each retry attempt. Evaluate
// whatever needed and decide if should retry.
return@shouldRetry true // or false if we don't wanna retry.
})
//...
.subscribe()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment