Using Futures in Akka Actors
Asked Answered
D

3

18

I'm just starting to learn Akka Actors in Scala. My understanding is that messages received by an Actor are queued in an Actor's mailbox, and processed one at a time. By processing messages one at a time, concurrency issues (race conditions, deadlocks) are mitigated.

But what happens if the Actor creates a future to do the work associated with a message? Since the future is async, the Actor could begin processing the next several messages while the future associated with the prior message is still running. Wouldn't this potentially create race conditions? How can one safely use futures within an Actor's receive() method to do long running tasks?

Decolonize answered 1/4, 2014 at 15:39 Comment(1)
do you mean action associated with the future operates on the variables internal to the actor? then yes, it is a race condition.Smuts
N
32

The safest way to use futures within an actor is to only ever use pipeTo on the future and send its result as a message to an actor (possibly the same actor).

import akka.pattern.pipe

object MyActor {

  def doItAsynchronously(implicit ec: ExecutionContext): Future[DoItResult] = { 
  /* ... */ 
  }

}

class MyActor extends Actor {

  import MyActor._    
  import context.dispatcher  

  def receive = {
    case DoIt =>
      doItAsynchronously.pipeTo(self)
    case DoItResult =>
       // Got a result from doing it
  }

}

This ensures that you won't mutate any state within the actor.

Nerte answered 1/4, 2014 at 16:34 Comment(2)
+1, and in case it wasn't clear from this Answer, doItAsynchronously should NOT mutate any state of the actor. In fact, if you can move that function to a companion object (or anything else that wouldn't have access to your actor's this), it'd be easier to keep yourself honest about that.Evening
Whilst this is an interesting pattern, it doesn't really answer the question: > Since the future is async, the Actor could begin processing the next several messages while the future associated with the prior message is still running. Wouldn't this potentially create race conditions? It only suggests now the work is done in parellel and could cause race conditions.Comprise
F
0

Remember two things

  1. The notion behind the term Future(a special actor) is that we can create an actor for any result while it(the result) is still being computed, started or finished but we can't have an address for that special actor or future.

  2. Suppose I want to buy something (my result is buying something, and the process it to initiate steps to start buying procedure) we can create an actor for the result (buy) but if there is any problem and we can't buy the thing we will have an exception instead of the result.

Now how the above two things fit is explained below-

Say we need to compute the factorial of 1 billion we may think that it will take a lot of time to compute but we get the Future immediately it will not take time to produce the Future (" Since the future is async, the Actor could begin processing the next several messages while the future associated with the prior message is still running."). Next, we can pass this future, store it and assign it.

Hope so you understand what I'm trying to say.

Src : https://www.brianstorti.com/the-actor-model/

Fagaceous answered 29/5, 2018 at 21:47 Comment(0)
M
-1

If you need to mutate state in futures without blocking incoming messages you might want to reconsider redesigning your actor model. I would introduce separate actors for each task you would use those futures on. After all, an actor's main task is to maintain its state without letting it escape thus providing safe concurrency. Define an actor for those long running task whose responsibility is only to take care of that.

Instead of taking care of the state manually you might want to consider using akka's FSM so you get a much cleaner picture of what changes when. I presonally prefer this approach to ugly variables when I'm dealing with more complex systems.

Mho answered 1/4, 2014 at 16:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.