Search code examples
scalascala-catscats-effect

Get back to IO fiber/thread after running a future


I have some cats IO operations, and Future among then. Simplified:

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

So I have some value in IO, then I need to do some blocking operation using a library that returns Future, and then I need to do some more processing on the value returned from Future

Future runs on a dedicated thread pool - so far so good. The problem is after Future is completed. moreProcessing runs on the same thread the Future was running on.

Is there a way to get back to the thread getValue() was running on?


Solution

  • After the discussion in the chat, the conclusion is that the only thing OP needs is to create a ContextShift in the application entry point using the appropriate (compute) EC and then pass it down to the class containing this method.

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

    This Scastie showed an approach using Blocker and other techniques common in the Typelevel ecosystem but were not really suitable for OP's use case; anyways I find it useful for future readers who may have a similar problem.