Accessing the sender of a message

When our fetcher manager receives a GiveMeWork request, we will need to send work back to the correct fetcher. We can access the actor who sent a message using the sender method, which is a method of Actor that returns the ActorRef corresponding to the actor who sent the message currently being processed. The case statement corresponding to GiveMeWork in the fetcher manager is therefore:

def receive = {
  case GiveMeWork =>
    login = // get next login to fetch
    sender ! Fetcher.Fetch(login)
  ...
}

As sender is a method, its return value will change for every new incoming message. It should therefore only be used synchronously with the receive method. In particular, using it in a future is dangerous:

def receive = {
  case DoSomeWork =>
    val work = Future { Thread.sleep(20000) ; 5 }
    work.onComplete { result => 
      sender ! Complete(result) // NO!
    }
}

The problem is that when the future is completed 20 seconds after the message is processed, the actor will, in all likelihood, be processing a different message so the return value of sender will have changed. We will thus send the Complete message to a completely different actor.

If you need to reply to a message outside of the receive method, such as when a future completes, you should bind the value of the current sender to a variable:

def receive = {
  case DoSomeWork =>
    // bind the current value of sender to a val
    val requestor = sender
    val work = Future { Thread.sleep(20000) ; 5 }
    work.onComplete { result => requestor ! Complete(result) }
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.14.93