【问题标题】:Get back to IO fiber/thread after running a future运行未来后返回 IO 光纤/线程
【发布时间】:2021-03-23 11:48:42
【问题描述】:

我有一些猫的 IO 操作,还有 Future 当中。简化:

IO(getValue())
  .flatMap(v => IO.fromFuture(IO(blockingProcessValue(v)))(myBlockingPoolContextShift))
  .map(moreProcessing)

所以我在IO中有一些值,那么我需要使用返回Future的库做一些阻塞操作,然后我需要对从Future返回的值做一些处理

Future 在专用线程池上运行 - 到目前为止一切顺利。问题是在Future 完成之后。 moreProcessingFuture 运行的同一线程上运行。

有没有办法回到 getValue() 正在运行的线程?

【问题讨论】:

  • 你有引用ExectutionContextContextShift 执行IO(getValue()) 吗?如果是这样,您可以通过以下方式转移执行:typelevel.org/cats-effect/api/cats/effect/…
  • 您应该收到一个 ContextShift 和一个 Blocker。这样你应该可以做类似flatMap(v => Blocker.blockOn(IO.fromFuture(IO(blockingProcessing(v))))
  • 但是我没有这个CS。 IO 一开始就运行的那个。这是一个显示问题的 sn-p:scastie.scala-lang.org/amorfis/FYL2vjGtSOqaN9Tx23vpZA/21
  • @amorfis 不要那样做,不要从阻塞执行上下文创建 ContextShift;实际上不要创建一个 ContextShift 请求一个。如果您使用的是 IOApp,运行时系统将为您提供一个 ContextShift 从主调用堆栈向下传递,直到您的代码,同样适用于 拦截器,在 main 中创建一个并将其显式传递给您的函数。

标签: scala scala-cats cats-effect


【解决方案1】:

经过聊天讨论,得出的结论是,OP 唯一需要做的就是使用适当的 (compute) EC 在应用程序入口点创建一个ContextShift strong> 然后将其传递给包含该方法的类。

// Entry point

val computeEC = ???
val cs = IO.contextShift(computeEC)
val myClass = new MyClass(cs, ...)

// Inside the method on MyClass
IO(getValue())
  .flatMap(v => IO.fromFuture(IO(blockingProcessValue(v)))(myBlockingPoolContextShift))
  .flatTap(_ => cs.shift)
  .map(moreProcessing)

这个Scastie 展示了一种使用BlockerTypelevel 生态系统中常见的其他技术的方法,但并不真正适合OP 的用例;无论如何,我发现它对可能有类似问题的未来读者很有用

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-31
    • 2016-12-01
    • 2015-06-25
    • 1970-01-01
    • 2021-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多