scala - Zio 运行阻止向后兼容的代码

标签 scala zio

(希望)关于 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% 向后兼容旧代码吗?

    最佳答案

    好的,我终于深入了解并实现了一些似乎满足我的要求的东西:

      /**
        * 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))
          }
        }
      }
    

    关于scala - Zio 运行阻止向后兼容的代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55380840/

    相关文章:

    scala类型和继承的误解

    java - 将类型化集合从 Scala 2.13 方法返回到 Java 8 调用者

    string - 如何在 Scala 中迭代列表的每个元素时修改它?

    scala - 如何在 ZIO 中实现不使用潜在大量堆空间的循环

    scala - 处理Scala ZIO中的错误

    scala - 如何与ZIO并行优雅地执行多种效果

    scala - scalaz 中的函数语法谜题

    scala - 测试是否在不提供参数的情况下调用了方法

    scala - 使用 ZIO 测试套件集成测试 HTTP 服务器

    scala - Zio,将 Seq[ZIO] 转换为 ZIO[Seq]