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 <R> repeatOnFailure(
+    onFailure: (Throwable) -> Boolean,
+    action: () -> R
+): Result<R> {
+    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 <R> repeatOnFailure(
     onEachFailure: (Throwable) -> Unit = {},
     action: (Int) -> R
 ): Optional<R> {
-    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()
 }