jem
04/02/2021, 6:48 AMfun <T> IO<T>.retry(
until: (T) -> Boolean = { true },
additionalTimes: Int = 4,
initialDelay: Duration = 500.milliseconds
): IO<T> {
val schedule = Schedule
.withMonad(IO.monad()) {
exponential<Either<Throwable, T>>(initialDelay)
.untilInput<Either<Throwable, T>> { it.exists(until) }
.and(recurs(additionalTimes))
.jittered(IO.monadDefer())
.zipRight(identity())
}
return map<Either<Throwable, T>> { it.right() }
.handleError { it.left() }
.repeat(IO.concurrent(dispatchers()), schedule).fix()
.flatMap {
it.fold({ throwable -> IO.raiseError(throwable) }, { t -> IO.just(t) })
}
}
simon.vergauwen
04/02/2021, 7:17 AMsuspend
instead of IO
this would look like this:
@ExperimentalTime
suspend fun <T> retry(
fa: suspend () -> T,
until: (T) -> Boolean = { true },
additionalTimes: Int = 4,
initialDelay: Duration = 500.milliseconds
): T {
val schedule =
Schedule.exponential<Either<Throwable, T>>(initialDelay)
.untilInput<Either<Throwable, T>> { it.exists(until) }
.and(Schedule.recurs(additionalTimes))
.jittered()
.zipRight(Schedule.identity())
return schedule.repeat {
Either.catch { fa() }
}.fold({ throwable -> throw throwable }, ::identity)
}
simon.vergauwen
04/02/2021, 7:19 AMIO
is deprecated in favor of Arrow Fx Coroutines and suspend
but you can find all the same functionality such as Schedule
there.
val arrowFxCoroutines = "io.arrow-kt:arrow-fx-coroutines:0.12.0"
jem
04/02/2021, 7:20 AM