Skip to content

Instantly share code, notes, and snippets.

@felipecsl
Last active April 27, 2023 00:02
Show Gist options
  • Save felipecsl/4323dada0db6e74d8757a756b254f45d to your computer and use it in GitHub Desktop.
Save felipecsl/4323dada0db6e74d8757a756b254f45d to your computer and use it in GitHub Desktop.
Kotlin utility to retry a provided block a limited number of times
/**
* Retries the provided [block] up to [times] times if the block throws an exception of the type
* [exceptionType]. If any other exception type is thrown, the exception is caught and then
* immediately rethrown.
*/
fun retryIfThrown(times: Int, exceptionType: KClass<out Throwable>, block: () -> Unit) {
for (i in 0 until times) {
try {
block()
break
} catch (e: Throwable) {
if (e.javaClass.kotlin == exceptionType && i < times - 1) {
println("Caught ${exceptionType.simpleName}, message=`${e.message}`. Retrying ${i + 1}/$times")
} else {
throw e
}
}
}
}
class UtilTest {
@Test fun `it should not retry`() {
var tries = 0
val block: () -> Unit = {
tries++
}
retryIfThrown(3, RuntimeException::class, block)
assertThat(tries).isEqualTo(1)
}
@Test fun `it should retry twice`() {
var tries = 0
val block = {
tries++
if (tries < 2) {
throw RuntimeException()
}
}
retryIfThrown(3, RuntimeException::class, block)
assertThat(tries).isEqualTo(2)
}
@Test(expected = RuntimeException::class)
fun `it should retry 3 times then rethrow the exception`() {
var tries = 0
val block = {
tries++
throw RuntimeException()
}
try {
retryIfThrown(3, RuntimeException::class, block)
} catch (e: Throwable) {
assertThat(tries).isEqualTo(3)
throw e
}
}
@Test(expected = IllegalArgumentException::class)
fun `it should not retry if exception is not of expected type`() {
var tries = 0
val block = {
tries++
throw IllegalArgumentException()
}
try {
retryIfThrown(3, RuntimeException::class, block)
} catch (e: Throwable) {
assertThat(tries).isEqualTo(1)
throw e
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment