Replacing concurrent calls wrapped in a future with cats effect IO

I know how to fire N concurrent http calls wrapped in futures. There is a thread pool defined. The N concurrent requests are executed on the threads in the thread pool. But if I had to replace Future with cats.effect.IO and obtain the same behaviour (10 concurrent requests), how should I go about doing that? How can I execute N IO requests concurrently?

parMapN is the easiest way:

val req1: IO[Response] = ???
val req2: IO[Response] = ???
...
val req10: IO[Response] = ???

(req1, req2, req3 ... req10).parMapN{ case (resp1, resp2, .... resp10) =>
/* do something with the responses */
}
2 Likes

parSequence possibly, or parTraverse.

import cats.effect.{IO, ExitCode, IOApp}
import cats.implicits._
import scala.concurrent.duration._

object App extends IOApp {
  def request(n: Int) = IO.sleep(5.seconds) *> IO(println(s"request $n")) 

  def run(args: List[String]) = 
    (1 to 10).toList.map(request).parSequence.as(ExitCode.Success)
}

Isn’t it parMapN if you want to execute them concurrently?

4 Likes

Yes, fixed!

1 Like

So, we don’t need to provide a thread pool executor here?

1 Like

It requires an implicit ContextShift[IO]. You can build one from a thread pool executor, or get one elsewhere, for example the default one in IOApp, which is backed by this ExecutionContext: https://github.com/typelevel/cats-effect/blob/series/2.x/core/jvm/src/main/scala/cats/effect/internals/PoolUtils.scala#L28

Full example with IOApp: https://scastie.scala-lang.org/aM3oMlbiTGe9OPAa4hMJLQ

2 Likes