Skip to content

Commit

Permalink
introduce retry on Either.Left
Browse files Browse the repository at this point in the history
  • Loading branch information
akotynski committed Feb 10, 2024
1 parent d42429f commit 7caa814
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import arrow.core.Either
import arrow.core.raise.Raise
import arrow.core.raise.either
import arrow.resilience.Schedule
import arrow.resilience.ScheduleStep
import kotlinx.coroutines.currentCoroutineContext
import kotlinx.coroutines.delay
import kotlinx.coroutines.ensureActive
import kotlin.time.Duration

public suspend fun <Error, Result, Output> Schedule<Error, Output>.retry(
action: suspend Raise<Error>.() -> Result,
): Either<Error, Result> {
var step: ScheduleStep<Error, Output> = step

while (true) {
currentCoroutineContext().ensureActive()
when (val result = either { action() }) {
is Either.Right -> return result
is Either.Left -> when (val decision = step(result.value)) {
is Schedule.Decision.Continue -> {
if (decision.delay != Duration.ZERO) delay(decision.delay)
step = decision.step
}

is Schedule.Decision.Done -> return result
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package arrow.resilience

import arrow.atomic.AtomicLong
import arrow.core.Either
import kotlinx.coroutines.test.TestResult
import kotlinx.coroutines.test.runTest
import retry
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue

class ScheduleEitherKtTest {

@Test
fun retryIsStackSafe(): TestResult = runTest {
val count = AtomicLong(0)
val iterations = 20_000L

val result = Schedule.recurs<CustomError>(iterations).retry {
count.incrementAndGet()
raise(CustomError)
}

assertTrue { result is Either.Left }
assertEquals(iterations + 1, count.get())
}

@Test
fun retrySucceedsIfRightIsReturned(): TestResult = runTest {
val result = Schedule.recurs<CustomError>(0).retry { 1 }

assertTrue { result is Either.Right && result.value == 1 }
}
}

private object CustomError

0 comments on commit 7caa814

Please sign in to comment.