0

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?

2
  • 3
    Two major things. 1 don't use IO.pure(println), use IO.println, probably that won't print anything, which means the problem is that you are not actually running your IO just constructing it. You may manually call unsafeRunSync() but you may also rather use the feral library: github.com/typelevel/feral Commented Apr 22 at 14:38
  • @LuisMiguelMejíaSuárez thanks you for response. Added answer on base of your comment. Commented Apr 22 at 18:43

1 Answer 1

2

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()
}

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.