commonMain.arrow.resilience.Schedule.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of arrow-resilience-jvm Show documentation
Show all versions of arrow-resilience-jvm Show documentation
Functional companion to Kotlin's Standard Library
@file:OptIn(ExperimentalTypeInference::class)
package arrow.resilience
import arrow.core.Either
import arrow.core.NonFatal
import arrow.core.None
import arrow.core.Option
import arrow.core.identity
import arrow.core.left
import arrow.core.merge
import arrow.core.nonFatalOrThrow
import arrow.core.raise.Raise
import arrow.core.raise.either
import arrow.core.raise.fold
import arrow.core.right
import arrow.core.some
import arrow.resilience.Schedule.Companion.identity
import arrow.resilience.Schedule.Decision
import arrow.resilience.Schedule.Decision.Continue
import arrow.resilience.Schedule.Decision.Done
import kotlinx.coroutines.currentCoroutineContext
import kotlinx.coroutines.delay
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.flow.retry
import kotlin.experimental.ExperimentalTypeInference
import kotlin.jvm.JvmInline
import kotlin.math.pow
import kotlin.random.Random
import kotlin.reflect.KClass
import kotlin.reflect.cast
import kotlin.time.Duration
import kotlin.time.Duration.Companion.ZERO
import kotlin.time.Duration.Companion.nanoseconds
public typealias ScheduleStep =
suspend (Input) -> Decision
/**
* A [Schedule] describes how a `suspend fun` should [retry] or [repeat].
*
* It's defined by a [step] function that takes an [Input] and returns a [Decision],
* the [Decision] determines if the `suspend fun` should be [Continue] to be retried or repeated
* (and if so, the `delay` until the next attempt),
* or if the [Schedule] is [Done] retrying or repeating.
*/
@JvmInline
public value class Schedule(public val step: ScheduleStep) {
/** Repeat the schedule, and uses [block] as [Input] for the [step] function. */
public suspend fun repeat(block: suspend () -> Input): Output =
repeatOrElse(block) { e, _ -> throw e }
/**
* Repeat the schedule, and uses [block] as [Input] for the [step] function.
* If the [step] function throws an exception, it will be caught and passed to [orElse].
*/
public suspend fun repeatOrElse(
block: suspend () -> Input,
orElse: suspend (error: Throwable, output: Output?) -> @UnsafeVariance Output
): Output = repeatOrElseEither(block, orElse).merge()
/**
* Repeat the schedule, and uses [block] as [Input] for the [step] function.
* If the [step] function throws an exception, it will be caught and passed to [orElse].
* The resulting [Either] indicates if the [step] function threw an exception or not.
*/
public suspend fun repeatOrElseEither(
block: suspend () -> Input,
orElse: suspend (error: Throwable, output: Output?) -> A
): Either {
var step: ScheduleStep = step
var state: Option
© 2015 - 2025 Weber Informatics LLC | Privacy Policy