scalaaws-lambdascala-catscats-effect

AWS Lambda not works with Cats Effect IO (Scala)


I try to run function written on Scala with Cats IO using. Simple Scala functions from https://aws.amazon.com/blogs/compute/writing-aws-lambda-functions-in-scala/ and https://rockthejvm.com/articles/deploy-a-scala-application-to-aws-lambda examples works fine. But when I try run function using Cats Effect IO like this:

  def execute: IO[Unit] = {
    for {
      task1 <- IO.pure(println("task 1"))
      task2 <- IO.pure(println("task 2"))
      task3 <- IO.pure(println("task 3"))
    } yield ()
  }

Only first task executes and function finishes. This is lambda log:

INIT_START Runtime Version: java:17.v42 Runtime Version ARN:arn:aws:lambda:eu-central-1::runtime:07e1a019fe488fb718021df9129caf01fd13d22d401104a151e929a91a82af7b
START RequestId:b032972f-4c47-4c9d-be22-c83141360bd7 Version: $LATEST
task 1 
END RequestId: b032972f-4c47-4c9d-be22-c83141360bd7 
REPORT RequestId: b032972f-4c47-4c9d-be22-c83141360bd7 Duration: 2211.47 ms Billed Duration: 2212 ms Memory Size: 512 MB Max Memory Used: 119 MB Init Duration: 577.36 ms

Looks like multithreading problem: task execution starts in parallel thread and program not waits while thread finishes. But yield() construction should sign that program should wait until all tasks finishes. And I not met any mentions that AWS Lambda have problems with multithreading, and IO really not run threads. What may be wrong?


Solution

  • Thanks to @LuisMiguelMejíaSuárez response solution was found. I created but not run IO. Working code sample below:

    def task: IO[Int] = {
      println("task 1")
      IO.pure(1)
    }
    
    def task2(i: Int): IO[Int] = {
      println(s"task 2: $i")
      IO.pure(i + 1)
    }
    
    def task3(i: Int): IO[Int] = {
      println(s"task 3: $i")
      IO.pure(i + 1)
    }
    
    def execute: Unit = {
    
      val mainIO = for {
        task1 <- task
        task2 <- task2(task1)
        _ <- task3(task2)
      } yield ()
    
      mainIO.handleError(ex => logger.error(ex.getMessage))
        .unsafeRunSync()
    }