diff --git a/common/src/commonMain/kotlin/dev/inmo/micro_utils/common/RepeatOnFailure.kt b/common/src/commonMain/kotlin/dev/inmo/micro_utils/common/RepeatOnFailure.kt index 409df8d2e98..4382ba40206 100644 --- a/common/src/commonMain/kotlin/dev/inmo/micro_utils/common/RepeatOnFailure.kt +++ b/common/src/commonMain/kotlin/dev/inmo/micro_utils/common/RepeatOnFailure.kt @@ -1,5 +1,27 @@ package dev.inmo.micro_utils.common +/** + * Executes the given [action] until getting of successful result specified number of [times]. + * + * A zero-based index of current iteration is passed as a parameter to [action]. + */ +inline fun repeatOnFailure( + onFailure: (Throwable) -> Boolean, + action: () -> R +): Result { + do { + runCatching { + action() + }.onFailure { + if (!onFailure(it)) { + return Result.failure(it) + } + }.onSuccess { + return Result.success(it) + } + } while (true) +} + /** * Executes the given [action] until getting of successful result specified number of [times]. * @@ -10,12 +32,23 @@ inline fun repeatOnFailure( onEachFailure: (Throwable) -> Unit = {}, action: (Int) -> R ): Optional { - repeat(times) { - runCatching { - action(it) - }.onFailure(onEachFailure).onSuccess { - return Optional.presented(it) + var i = 0 + val result = repeatOnFailure( + { + onEachFailure(it) + if (i < times) { + i++ + true + } else { + false + } } + ) { + action(i) + } + return if (result.isSuccess) { + Optional.presented(result.getOrThrow()) + } else { + Optional.absent() } - return Optional.absent() }