0

I'm referring to this answer for one retryIO in my timer. the code is here:

suspend fun <T> retryIO(
    times: Int = Int.MAX_VALUE,
    initialDelay: Long = 100, // 0.1 second
    maxDelay: Long = 1000,    // 1 second
    factor: Double = 2.0,
    block: suspend () -> T): T
{
    var currentDelay = initialDelay
    repeat(times-1) {
        try {
            return block()
        } catch (e: IOException) {
            Timber.i("retryIO repeat ${it} failed")
            Timber.e(e)
        }
        delay(currentDelay)
        currentDelay = (currentDelay * factor).toLong().coerceAtMost(maxDelay)
    }
    Timber.i("retryIO run final block")
    return block() // last attempt as final
}

Then i use one kotlin timer to call one GET to check the service status and update the ui.

timer(initialDelay = 10000L, period = 10000L ) {
    CoroutineScope(Dispatchers.IO).launch {
        try {
            val result = retryIO(times = 3) {
                api.doGetHealth().await()
            }
            Timber.i("retryIO")
            CoroutineScope(Dispatchers.Main).launch {
                updateHealthStatus(HealthStatus.CONNECTED)
            }
        }
        catch (e: IOException) {
            Timber.i("retryIO failed")
            Timber.e(e)
            CoroutineScope(Dispatchers.Main).launch {
                updateHealthStatus(HealthStatus.DISCONNECTED)
            }
        }
    }
}

I'm expecting if try to call the service 3 times with error, then the last call will throw some exception which will be caught in the "retryIO failed" catch, then we can update the ui with disconnected. but it's not working.

The current logs is as below:

2022-06-03 09:12:34.470 21614-28139/com. I/MainActivity$onCreate$$inlined$timer$1$lambda: retryIO
2022-06-03 09:12:44.508 21614-28139/com. I/MainActivity$onCreate$$inlined$timer$1$lambda: retryIO
2022-06-03 09:14:04.345 21614-28139/com. I/UtilsKt: retryIO repeat 0 failed // turn off the network to cause the timeout exception
2022-06-03 09:14:14.347 21614-28139/com. I/UtilsKt: retryIO repeat 0 failed
2022-06-03 09:14:24.327 21614-28139/com. I/UtilsKt: retryIO repeat 0 failed
2022-06-03 09:14:54.401 21614-28139/com. I/UtilsKt: retryIO repeat 0 failed
2022-06-03 09:15:05.849 21614-28139/com. I/UtilsKt: retryIO repeat 0 failed
2022-06-03 09:15:14.415 21614-28139/com. I/UtilsKt: retryIO repeat 0 failed
2022-06-03 09:15:54.445 21614-28139/com. I/UtilsKt: retryIO repeat 0 failed
2022-06-03 09:16:04.524 21614-28139/com. I/UtilsKt: retryIO repeat 0 failed
2022-06-03 09:16:05.924 21614-28139/com. I/UtilsKt: retryIO repeat 1 failed
2022-06-03 09:16:24.461 21614-28139/com. I/UtilsKt: retryIO repeat 0 failed
2022-06-03 09:16:54.493 21614-28139/com. I/UtilsKt: retryIO repeat 1 failed
2022-06-03 09:17:04.564 21614-28139/com. I/UtilsKt: retryIO repeat 0 failed
2022-06-03 09:17:05.982 21614-28139/com. I/UtilsKt: retryIO repeat 1 failed
2022-06-03 09:17:24.526 21614-28139/com. I/UtilsKt: retryIO repeat 0 failed

The expected behaviour is if network is off, then it will try 3 times then the thrown exception will be caught and processed with updateHealthStatus(HealthStatus.DISCONNECTED). it seems this times = 3 is also not working. the repeat 0 happens 8 times and the "retryIO run final block" still not print.

chancyWu
  • 14,073
  • 11
  • 62
  • 81
  • Are you certain that `api.doGetHealth().await()` will only throw exceptions of type `IOException`? What do you mean by its not working? What are you expecting to happen, and what is actually happening? – TheJakester42 Jun 02 '22 at 19:39
  • @TheJakester42 add more logs and explanation. – chancyWu Jun 03 '22 at 01:26
  • Will you show more code? Where is `timer()` called from? Specifically, where are you getting your initial coroutine scope? To me, those logs look like the coroutine scope that you are using is getting canceled before your `delay(currentDelay)` finishes. Then something else restarts the scope and retrys. – TheJakester42 Jun 03 '22 at 22:43

0 Answers0