Repeat
The repeat functions allow to repeat an operation according to a given schedule (e.g. repeat 3 times with a 100ms
interval and 50ms of initial delay).
API
The basic syntax for repeat is:
import ox.scheduling.repeat
repeat(config)(operation)
The repeat API uses scheduled underneath with DSL focused on repeats. See scheduled for more details.
Operation definition
Similarly to the retry API, the operation can be defined:
directly using a by-name parameter, i.e.
f: => Tusing a by-name
Either[E, T]or using an arbitrary error mode, accepting the computation in an
Fcontext:f: => F[T].
Configuration
The repeat config requires a Schedule, which indicates how many times and with what interval should the operation
be repeated.
In addition, it is possible to define a custom shouldContinueOnSuccess strategy for deciding if the operation
should continue to be repeated after a successful result returned by the previous operation (defaults to _: T => true).
If an operation returns an error, the repeat loop will always be stopped. If an error handling within the operation
is needed, you can use a retry inside it (see an example below) or use scheduled instead of repeat, which allows
full customization.
API shorthands
You can use one of the following shorthands to define a RepeatConfig with a given schedule with an optional initial delay:
RepeatConfig.immediate(maxInvocations: Int, initialDelay: Option[FiniteDuration] = None)RepeatConfig.immediateForever[E, T](initialDelay: Option[FiniteDuration] = None)RepeatConfig.fixedRate[E, T](maxInvocations: Int, interval: FiniteDuration, initialDelay: Option[FiniteDuration] = None)RepeatConfig.fixedRateForever[E, T](interval: FiniteDuration, initialDelay: Option[FiniteDuration] = None)RepeatConfig.backoff[E, T](maxInvocations: Int, firstInterval: FiniteDuration, maxInterval: FiniteDuration = 1.minute, jitter: Jitter = Jitter.None, initialDelay: Option[FiniteDuration] = None)RepeatConfig.backoffForever[E, T](firstInterval: FiniteDuration, maxInterval: FiniteDuration = 1.minute, jitter: Jitter = Jitter.None, initialDelay: Option[FiniteDuration] = None)
See scheduled for details on how to create custom schedules.
Examples
import ox.UnionMode
import ox.scheduling.{Schedule, repeat, repeatEither, repeatWithErrorMode, RepeatConfig}
import ox.resilience.{retry, RetryConfig}
import scala.concurrent.duration.*
def directOperation: Int = ???
def eitherOperation: Either[String, Int] = ???
def unionOperation: String | Int = ???
// various operation definitions - same syntax
repeat(RepeatConfig.immediate(3))(directOperation)
repeatEither(RepeatConfig.immediate(3))(eitherOperation)
// various schedules
repeat(RepeatConfig.fixedRate(3, 100.millis))(directOperation)
repeat(RepeatConfig.fixedRate(3, 100.millis, Some(50.millis)))(directOperation)
// infinite repeats with a custom strategy
def customStopStrategy: Int => Boolean = ???
repeat(RepeatConfig.fixedRateForever(100.millis).copy(shouldContinueOnResult = customStopStrategy))(directOperation)
// custom error mode
repeatWithErrorMode(UnionMode[String])(RepeatConfig.fixedRate(3, 100.millis))(unionOperation)
// repeat with retry inside
repeat(RepeatConfig.fixedRate(3, 100.millis)) {
retry(RetryConfig.backoff(3, 100.millis))(directOperation)
}