简体   繁体   中英

fs2 Stream from queue doesn't consume elements

I want to create the stream from the queue that will print all the elements into the console. The current one snippet doesn't print anything:

object TestApp extends App {

  implicit val contextShift: ContextShift[IO] = IO.contextShift(ExecutionContext.global)

  private val value: IO[(fs2.Stream[IO, Unit], String => IO[Unit], () => IO[Unit])] = for {
    queue <- Queue.noneTerminated[IO, String]
  } yield {
    val stream: fs2.Stream[IO, Unit] = queue.dequeue.map(println)

    def send(msg: String): IO[Unit] = queue.enqueue1(Some(msg))

    def close(): IO[Unit] = queue.enqueue1(None)

    (stream, send _, close _)
  }

  val (stream, send, close) = value.unsafeRunSync()

  send("msg1").unsafeRunSync()
  send("msg2").unsafeRunSync()

}

what is wrong with stream creation?

In your example, you're merely creating a queue and creating a description of the stream. In order to run the stream, you need to call compile which will expose several methods, that would allow running and consuming values of the steam, like toList , fold or drain

In your case you're not really interested in values, since you only want to print them, so you should use drain :

implicit val contextShift: ContextShift[IO] = IO.contextShift(ExecutionContext.global)
implicit val timer: Timer[IO] = IO.timer(ExecutionContext.global)

private val value: IO[(fs2.Stream[IO, Unit], String => IO[Unit], () => IO[Unit])] = for {
  queue <- Queue.noneTerminated[IO, String]
} yield {
  //I changed map to evalMap, since printing is effect and should be wrapped in IO
  val stream: fs2.Stream[IO, Unit] = queue.dequeue.evalMap(v => IO(println(v)))

  def send(msg: String): IO[Unit] = queue.enqueue1(Some(msg))

  def close(): IO[Unit] = queue.enqueue1(None)

  (stream, send _, close _)
}

val (stream, send, close) = value.unsafeRunSync()

send("msg1").unsafeRunSync()
send("msg2").unsafeRunSync()
//Closing of stream will be delayed by 5s and run in separate fiber
close().delayBy(5.seconds).start.unsafeRunSync()

//steam would block here until it's closed
stream.compile.drain.unsafeRunSync()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM