cutoffurmind
cutoffurmind

Reputation: 487

Play 2.7 background tasks and async services

I’m wondering what is the correct way to work with async services (returns Future[OfResult]) inside Play background akka tasks. There is no information about it in play docs, It seems I can’t just return Future[TaskResult] at the end and get things done in a reactive way, so I’m using Await.result for each async service call. And even if I use my own custom execution context, sometimes I get weird exceptions from slick db layer and task stops working, this is not resilient at all (I would expect at least next schedule to work) so I think I’m doing it wrong.

The task is simple, I have an events table in database with some fields and date range, each day I’m checking if current date is inside date range, I remove passed events and activate new events. It requires me to:

  1. Get all events - which is list of Future[Event]
  2. Get through the list and modify or delete events

I’m doing it in procedural style with blocking Await.result

With small events count it fails very rare but with like thousands - it fails pretty soon (I assume because of limited database pool?)

It doesn’t look like just wrong database configuration because in regular async controller action everything works fine with huge amount of data so I suppose I’m doing it wrong

Upvotes: 0

Views: 41

Answers (1)

johanandren
johanandren

Reputation: 11479

You should never use Await.result in application logic as it will block the calling thread and potentially starve your threadpool. See more in the Akka docs here: https://doc.akka.io/docs/akka/current/typed/dispatchers.html#blocking-needs-careful-management . This could be why you are seeing it failing.

If a future depends on another you should chain them using map or flatMap. For turning a List[Future[T]] into a Future[List[T]] you can use Future.sequence.

If what you mean with "background akka tasks" is using the scheduler of the ActorSystem like in this article there is no need for the operation to block the Runnable passed to the scheduler for the duration, just let it trigger your future tasks and then return.

It is important to understand that the future operations will execute on one or more other threads, so if you want to observe that it progresses and completes or fails you will have to add that with callbacks on the futures (for example onComplete on the final future).

Upvotes: 1

Related Questions