Skip to content
This repository has been archived by the owner on Feb 24, 2021. It is now read-only.

Fix Schedule type in retry methods #297

Merged
merged 4 commits into from
Nov 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -792,7 +792,7 @@ suspend fun <A, B, C> repeatOrElseEither(
* Returns the result of the effect if if it was successful or re-raises the last error encountered when the schedule ends.
*/
suspend fun <A, B> retry(
schedule: Schedule<A, B>,
schedule: Schedule<Throwable, B>,
fa: suspend () -> A
): A = retryOrElse(schedule, fa) { e, _ -> throw e }

Expand All @@ -801,7 +801,7 @@ suspend fun <A, B> retry(
* Also offers a function to handle errors if they are encountered during retrial.
*/
suspend fun <A, B> retryOrElse(
schedule: Schedule<A, B>,
schedule: Schedule<Throwable, B>,
fa: suspend () -> A,
orElse: suspend (Throwable, B) -> A
): A = retryOrElseEither(schedule, fa, orElse).fold(::identity, ::identity)
Expand All @@ -812,7 +812,7 @@ suspend fun <A, B> retryOrElse(
*/
@Suppress("UNCHECKED_CAST")
suspend fun <A, B, C> retryOrElseEither(
schedule: Schedule<A, B>,
schedule: Schedule<Throwable, B>,
fa: suspend () -> A,
orElse: suspend (Throwable, B) -> C
): Either<C, A> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package arrow.fx.coroutines

import arrow.core.Either
import arrow.core.Eval
import io.kotest.assertions.fail
import io.kotest.matchers.shouldBe
import kotlin.math.pow

Expand Down Expand Up @@ -175,10 +176,21 @@ class ScheduleTest : ArrowFxSpec(spec = {
l shouldBe Either.Left(stop)
}

"repeat fails fast on errors" {
val ex = Throwable("Hello")
repeatOrElseEither(Schedule.recurs(0), { throw ex }) { exc, _ -> exc }
.fold({ it shouldBe ex }, { fail("The impossible happened") })
}

"repeat should run the schedule with the correct input" {
var i = 0
repeat(Schedule.recurs<Int>(10).zipRight(Schedule.collect())) { i++ } shouldBe (0..10).toList()
}

"retry is stack-safe" {
val count = Atomic(0)
val l = Either.catch {
val n: Nothing = retry(Schedule.recurs(20_000)) {
retry(Schedule.recurs(20_000)) {
count.updateAndGet { it + 1 }
throw exception
}
Expand All @@ -187,6 +199,18 @@ class ScheduleTest : ArrowFxSpec(spec = {
l shouldBe Either.Left(exception)
count.get() shouldBe 20_001
}

"retry succeeds if no exception is thrown" {
retry(Schedule.recurs(0)) { 1 } shouldBe 1
}

"retryOrElseEither runs the schedule with the correct input and runs the orElse handler if it does not retry" {
val ex = Throwable("Hello")
val res = retryOrElseEither<Int, Int, Throwable>(Schedule.recurs(0), {
throw ex
}) { e, _ -> e }
res.fold({ it shouldBe ex }, { fail("The impossible happened") })
}
})

private fun fibs(one: Long): Sequence<Long> = generateSequence(Pair(0L, one)) { (a, b) ->
Expand Down