I have a generic `retry` function that takes an `a...
# coroutines
r
I have a generic
retry
function that takes an
action
lambda. Is there a way for me to define this function in such a way that the
action
lambda can be either suspending or non-suspending depending on the caller?
l
A
suspend
lambda can not suspend. The contrary is not possible, unless you want to go down the dark route of
runBlocking
r
Yeah, a
retry
is a peculiar case, because if I make the lambda suspendable, then the
tryAction
function I call it in with all of the error handling logic has to be suspending as well. But if I make that suspending, then the
retry
function has to be suspending.
This is my current (slightly simplified) implementation:
Copy code
fun <T> retry(maxAttempts: Int = 3,
  delay: Long = 1000,
  action: () -> T): T = tryAction(0, maxAttempts, delay, action)

fun <T> tryAction(currentAttempt: Int, maxAttempts: Int, delay: Long, action: () -> T): T {

  return try {
    action.invoke()
  } catch (e: Exception) {
    if (currentAttempt + 1 < maxAttempts) {
      if(delay > 0) try { Thread.sleep(delay) } catch (e: InterruptedException) { /* ignore */ }
      tryAction(currentAttempt + 1, maxAttempts, delay, action)
    } else {
      throw e
    }
  }
}
I'm thinking I'd like to make this all suspending (which means I can use
delay
there instead of sleep also), and then have a
retryBlocking
wrapper for non-suspending callers.
e
Yes. That is the way to do it.
👍 2