I am using akka for some time. I started to see some patterns in my code to solve late reply for async io. Is this implementation ok? There is another way to do a late reply without block?
class ApplicationApi(asyncIo : ActorRef) extends Actor {
// store senders to late reply
val waiting = Map[request, ActorRef]()
def receive = {
// an actore request for a user, store it to late reply and ask for asyncIo actor to do the real job
case request : GetUser =>
waiting += (sender -> request)
asyncIo ! AsyncGet("http://app/user/" + request.userId)
// asyncio response, parse and reply
case response : AsyncResponse =>
val user = parseUser(response.body)
waiting.remove(response.request) match {
case Some(actor) => actor ! GetUserResponse(user)
}
}
}
One way to avoid blocking while waiting for a reply is to send using the
askmethod—a.k.a.?operator—which returns aFuture(unlike!which returns()).Using the
onSuccessorforeachmethods, you can specify actions to be performed if/when the future is completed with a reply. To use this you need to mix in theAskSupporttrait:Avoid using this technique to perform any side effect that modifies the state of the
ApplicationApiactor, because the effect will happen out-of-sync with the receive loop. Forwarding messages to other actors should be safe, though.By the way, here is a trick to capture the current
senderas part of the pattern match, avoiding the need to assign it to a variable later.