I have a Actor, and on some message I'm running some method which returns Future.
def receive: Receive = {
case SimpleMessge() =>
val futData:Future[Int] = ...
futData.map { data =>
...
}
}
Is it possible to pass actual context to wait for this data? Or Await
is the best I can do if I need this data in SimpleMessage?
If you really need to wait for the future to complete before processing the next message, you can try something like this:
object SimpleMessageHandler{
case class SimpleMessage()
case class FinishSimpleMessage(i:Int)
}
class SimpleMessageHandler extends Actor with Stash{
import SimpleMessageHandler._
import context._
import akka.pattern.pipe
def receive = waitingForMessage
def waitingForMessage: Receive = {
case SimpleMessage() =>
val futData:Future[Int] = ...
futData.map(FinishSimpleMessage(_)) pipeTo self
context.become(waitingToFinish(sender))
}
def waitingToFinish(originalSender:ActorRef):Receive = {
case SimpleMessage() => stash()
case FinishSimpleMessage(i) =>
//Do whatever you need to do to finish here
...
unstashAll()
context.become(waitingForMessage)
case Status.Failure(ex) =>
//log error here
unstashAll()
context.become(waitingForMessage)
}
}
In this approach, we process a SimpleMessage
and then switch handling logic to stash all subsequent SimpleMessage
s received until we get a result from the future. When we get a result, failure or not, we unstash all of the other SimpleMessage
s we have received while waiting for the future and go on our merry way.
This actor just toggles back and forth between two states and that allows you to only fully process one SimpleMessage
at a time without needing to block on the Future.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With