Search code examples
scalacats-effect

Sequential execution of IO from Future


I have simple combinations of two IO with sending message to Telegram bot

def send:Future[Message] = request(SendMessage(chatID, msg))

How to combine IO in greeting to get output "second" after "first" every time. I tried to use *>, flatMap, IO.fromFuture but the result was different.

first
second

second 
first
  def greeting(chatId: Long): IO[Unit] =
    IO(request(SendMessage(chatId, "first"))) *>
    IO(request(SendMessage(chatId, "second")))

  override def onMessage(message: Message) = message.text match {
    case Some(_) => greeting(message.chat.id)
      .unsafeRunAsyncAndForget()
  }

Solution

  • The following snippet works, it does not start the second IO / Future until the first one completes.

    import scala.concurrent.Future
    import scala.concurrent.ExecutionContext.Implicits.global
    import cats.effect.IO
    
    def send(message: => String): Future[Unit] =
      Future {
        Thread.sleep(2000);
        println(message)
      }
    
    def greeting: IO[Unit] =
      for {
       _ <- IO.fromFuture(IO(send("First")))
       _ <- IO.fromFuture(IO(send("Second")))
      } yield ()
    
    greeting.unsafeRunAsyncAndForget()