igx
igx

Reputation: 4231

Are futures blocked in the receive method of Actors

Just a question : I have an actor that queries the db (assume that queries take some time) . all results from db are returning a Future . this is basically they way we do it :

case class BasePay(id:String,baseSalary)
class CalcActor(db:DB) extends Actor{
 override def receive: Receive = {
    case BasePay(id:String,baseSalary) => 
      for{
          person <- db.longQueryToFindPerson(id)
          calc <- db.anotherLongQueryCallCommission(person,baseSalary)
       }yield Foo(person,calc)
}

what happens if I get a lot of BasePay messages before the futures completes ? is it queued ? are there other failures I should notice here ?

Upvotes: 0

Views: 71

Answers (3)

Luis Ramirez-Monterosa
Luis Ramirez-Monterosa

Reputation: 2242

the for comprehension uses a context to execute your code

  for{
      person <- db.longQueryToFindPerson(id)
      calc <- db.anotherLongQueryCallCommission(person,baseSalary)
   }yield Foo(person,calc)

this is actually desugar into

db.longQueryToFindPerson(id).flatMap(person => 
    db.anotherLongQueryCallCommission(person,baseSalary)
        .map(calc => Foo(person,calc))(aContext)//if no context will use implicit in this case the dispatcher assigned to the actor

but future flatmap requires a context to run, given that none is provided it will use an implicit context

in this case will be using the dispatcher assigned to your actor, therefore, your actor will be competing for threads allocation with the futures being executed. So your actor will increase its mailbox until dispatcher is able to process the futures.

you can specify another dispatcher to run the futures, there different ways.

   implicit val context = ExecutionContext.fromExecutor(//etc)
   for{
      person <- db.longQueryToFindPerson(id)
      calc <- db.anotherLongQueryCallCommission(person,baseSalary)
   }yield Foo(person,calc)

Upvotes: 1

mhashim
mhashim

Reputation: 113

if this is the default mailbox, i.e you didn't specify a mailbox in some way then its non-blocking and unbounded so its OK as long as you don't run out of memory. check the documentation for even more info.

Upvotes: 0

Michael Zajac
Michael Zajac

Reputation: 55569

What happens if I get a lot of BasePay messages before the futures completes?

A lot of futures will be executed, regardless of when the first one completes.

Is it queued?

No. The only way to have it queue would be to block on the Future result. Since the Future is dispatched asynchronously, the actor is able to continue processing messages.

Are there other failures I should notice here?

This is a broad question. Since that looks like example code, it is difficult to speculate what could go wrong. You could quickly exhaust any sort of connection pool by dispatching many queries at the same time. That can be limited by creating an ExecutionContext with a limited size to throttle how many of the Futures are executed at the same time, but that would not limit the actor from accepting the messages rapidly.

Upvotes: 4

Related Questions