Last active
January 7, 2021 12:35
-
-
Save TemMax/afe105ec1324259970bfbb7a30a5d91f to your computer and use it in GitHub Desktop.
A function that wraps another suspend function for exponential retry
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* A function that wraps another suspend function for exponential retry | |
* | |
* @param count number of retires | |
* @param initialDelay millis between retries | |
* @param maxDelay max millis of delay from exponential backoff strategy | |
* @param factor delay multiplier | |
* @param predicate true — need continue retries, false — rethrows Throwable to caller | |
* @param block function to execute | |
* | |
* @return result of block() parameter | |
*/ | |
suspend fun <T> retry( | |
count: Int, | |
initialDelay: Long = 100L, | |
maxDelay: Long = 1000L, | |
factor: Float = 2.0F, | |
predicate: (cause: Throwable) -> Boolean = { true }, | |
block: suspend () -> T | |
): T { | |
require(count > 0) { "Count must be > 0" } | |
require(initialDelay > 0L) { "Delay must be > 0" } | |
require(maxDelay >= initialDelay) { "Max delay must be >= Delay" } | |
require(factor > 1F) { "Factor must be > 1" } | |
var currentDelay = initialDelay | |
repeat(count - 1) { | |
try { | |
return block() | |
} catch (e: Exception) { | |
if (predicate(e)) { | |
delay(currentDelay) | |
currentDelay = (currentDelay * factor).toLong().coerceAtMost(maxDelay) | |
} else { | |
throw e | |
} | |
} | |
} | |
return block() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment