(希望如此)关于Scalaz Zio的简单问题。
我有一些重构到Zio的旧代码。我希望该代码的一个路径保持其原来的状态:
如何运行IO
使其表现得像旧的阻止代码?
我目前正在使用:
private lazy val blockingRts = new RTS {}
def runBlocking[E, A](io: IO[E, A]): Either[E, A] = {
blockingRts.unsafeRun(io.attempt)
}
这似乎可以解决问题,但我不确定这是正确的。这是100%向后兼容旧代码吗?
答案 0 :(得分:1)
好吧,我终于在后台进行了检查,并执行了一些似乎可以满足我要求的事情:
/**
* Executes the IO synchronous and blocking on the current thread, thus running an IO
* without any of the advantages of IO. This can be useful for maintaining backwards compatibility.
* Rethrows any exception that was not handled by the IO's error handling.
*/
@throws
def runLegacy[E, A](io: IO[E, A]): Either[E, A] = {
syncBlockingRunTimeSystem.unsafeRunSync[Nothing, Either[E, A]](io.either) match {
case Exit.Success(v) => v
case Exit.Failure(Cause.Die(exception)) => throw exception
case Exit.Failure(Cause.Interrupt) => throw new InterruptedException
case Exit.Failure(fail) => throw FiberFailure(fail)
}
}
private lazy val syncBlockingRunTimeSystem = Runtime(
(),
PlatformLive.fromExecutor(new Executor {
override def yieldOpCount: Int = Int.MaxValue
override def metrics: Option[ExecutionMetrics] = None
override def submit(runnable: Runnable): Boolean = {
runnable.run()
true
}
override def here: Boolean = true
})
)
我还写了一些测试:
"runLegacy" should {
"run synchronous code in blocking fashion on current thread" in {
var runCount = 0
val io = IO.succeedLazy { runCount += 1 }
.map { _ => runCount +=1 }
.flatMap { _ =>
runCount += 1
IO.effect {
runCount += 1
Thread.currentThread()
}
}
runCount shouldBe 0
runLegacy(io) shouldBe Right(Thread.currentThread())
runCount shouldBe 4
}
"run parallel code sequentially on current thread" in {
val ios = (1 to 500).map { i => IO.succeedLazy { i } }
runLegacy(IO.reduceAll(IO.succeed(0), ios) {
case (a, b) => a + b
}) shouldBe Right((500 * 501) / 2)
}
"run many flatMaps without overflowing" in {
var runCount = 0
val io = IO.succeedLazy { runCount += 1 }
val manyIo = (1 to 9999).foldLeft(io) { case (acc, _) => acc.flatMap { _ => io } }
runLegacy(manyIo)
runCount shouldBe 10000
}
case object TestException extends Throwable
"handle sync blocking errors" in {
case object TestException extends Throwable
runLegacy(IO.effect(throw TestException)) shouldBe Left(TestException)
}
"rethrow unhandled exceptions" in {
assertThrows[TestException.type] {
runLegacy(IO.succeedLazy(throw TestException))
}
}
}