import zio._
Schedules 允许你定义和编写灵活的重复执行调度器,这些事件可以是重复的计算,或在出现错误时重试操作。Schedules 被用于以下场景:
- 重复
IO#repeat
—— 重复执行 effect,直到调度计划结束。IO#repeatOrElse
—— 重复执行 effect,直到调度计划完成,如果得到错误,则返回另一个 effect 的结果。IO#repeatOrElse0
—— 重复执行 effect,直到调度计划完成,如果得到错误,则返回另一个具有更多(定制)能力的 effect 的结果。
- Retries
IO#retry
—— 重试一个 effect 直到成功。IO#retryOrElse
—— 运行一个 effect,如果失败则尝试另一个 effect,不断重试两者直到成功。IO#retryOrElse0
—— 运行一个 effect,如果失败则尝试另一个具有更多(定制)能力的 effect,不断重试两者直到成功。
Schedules 定义了有状态的,可能有效果的事件的重复执行调度计划,并以允许以多种方式进行组合。
Contents
hide
一个 Schedule[R, A, B]
它的输入类型为 A(A 在 retry
情况下为(前一调用的)错误类型,或在 repeat 情况下为(前一调用的)输出类型),并根据这些值和内部状态决定是重复执行还是返回结果。每个决策都会伴随(可能为零的)延迟,该延迟指示下一次重复发生之前需要多少时间停顿,并最终得到 B 类型输出值。
基本的 Schedules
一个永远循环的 Schedule:
val forever = Schedule.forever
一个循环 10 次的 Schedule:
val upTo10 = Schedule.recurs(10)
一个每 10 毫秒循环一次的 Schedule:
val spaced = Schedule.spaced(10.milliseconds)
(缺省为平方)指数延迟的 Scheduler
val exponential = Schedule.exponential(10.milliseconds)
以 fibonacci 计数(每次延迟是前两次延迟之和)的延迟:
val fibonacci = Schedule.fibonacci(10.milliseconds)
Schedule 组合器
给 Schedule 附加一个随机修正值。
val jitteredExp = Schedule.exponential(10.milliseconds).jittered
修改 schedule 的延迟间隔:
val boosted = Schedule.spaced(1.second).delayed(_ => 100.milliseconds)
依次串行组合两个调度器,先遵循第一个策略直到结束,然后遵循第二个策略直到结束:
val sequential = Schedule.recurs(10) andThen Schedule.spaced(1.second)
合并两个调度器(取交集),仅在两个调度器都得到满足时才以两者之间的最大延迟重复执行调度:
val expUpTo10 = Schedule.exponential(1.second) && Schedule.recurs(10)
合并两个调度器(取并集),如果两个调度计划中的任何一个想要重复执行,则使用两次重复之间的最小延迟来重复:
val expCapped = Schedule.exponential(100.milliseconds) || Schedule.spaced(1.second)
经过指定的时间后,停止重试:
val expMaxElapsed = (Schedule.exponential(10.milliseconds) >>> Schedule.elapsed).whileOutput(_ < 30.seconds)
仅在发生特定异常时重试:
import scala.concurrent.TimeoutException
val whileTimeout = Schedule.exponential(10.milliseconds) && Schedule.recurWhile[Throwable] {
case _: TimeoutException => true
case _ => false
}