假设我有一个 IO(因此不安全)操作将返回true
或false
. 我想使用 Zio 调度机制来执行此操作,直到值为true
,但最多只能执行 N 次。采用文档中的代码并将其更改为我想要实现的...
import zio._
import zio.duration._
import zio.console._
import zio.clock._
import java.util.Random
object API {
// our API method will return true about 30% of the time, but
// return false the rest of the time (instead of throwing an
// exception, as is shown in documentation)
def makeRequest: Task[Boolean] = Task.effect {
new Random().nextInt(10) > 7
}
}
object ScheduleUtil {
def schedule[A] = Schedule.spaced(1.second) && Schedule.recurs(4).onDecision({
case Decision.Done(_) => putStrLn(s"done trying")
case Decision.Continue(attempt, _, _) => putStrLn(s"attempt #$attempt")
})
}
import ScheduleUtil._
import API._
object ScheduleApp extends scala.App {
implicit val rt: Runtime[Clock with Console] = Runtime.default
rt.unsafeRun(makeRequest.retry(schedule).foldM(
ex => putStrLn("Exception Failed"),
v => putStrLn(s"Succeeded with $v"))
)
}
// run the app
ScheduleApp.main(Array())
这当然行不通。输出是Succeeded with false
or (偶尔) Succeeded with true
。我尝试添加Schedule.recurUntilEquals
到Schedule
定义中,但无济于事。
object ScheduleUtil {
def schedule[A] = Schedule.spaced(1.second) && Schedule.recurUntilEquals(true) && Schedule.recurs(4).onDecision({
case Decision.Done(_) => putStrLn(s"done trying")
case Decision.Continue(attempt, _, _) => putStrLn(s"attempt #$attempt")
})
}
import ScheduleUtil._
// re-define ScheduleApp in the exact same way as above, and the following error results:
cmd93.sc:5: polymorphic expression cannot be instantiated to expected type;
found : [A]zio.Schedule[zio.console.Console,Boolean,((Long, Boolean), Long)]
(which expands to) [A]zio.Schedule[zio.Has[zio.console.Console.Service],Boolean,((Long, Boolean), Long)]
required: zio.Schedule[?,Throwable,?]
rt.unsafeRun(makeRequest.retry(schedule).foldM(
如何使用 Zio 调度程序完成这样的用例?当然,我可以重新定义makeRequest
任务以故意抛出异常,而不是返回 false,这与文档中的工作方式一样。但我希望避免不必要的异常生成/处理。
object API {
// our API method will return true about 30% of the time, but
// return false the rest of the time (instead of throwing an
// exception, as is shown in documentation)
def makeRequest = Task.effect {
if (new Random().nextInt(10) > 7) true else throw new Exception("Not true")
}
}