Search code examples
akkaactorakka-http

Could akka actor reply message in different case


I am using Akka HTTP and have a AnswerActor, I want to do following thing.

class AnswerActor() extends Actor {
  var requestMap = mutable.Map[String, ActorRef]()
  ...
  override def receive: Receive = {
// I want to store sender() here instead of reply in this case, because my reply is not available at this moment
    case message: M1 => requestMap.put(sender().path.name -> sender()) 

// I want to reply when I receive M2, my reply is available now
    case message: M2 => requestMap.get(...) ! MyReply 

I use val ans = Await.result(questionActor ? M1) , and another actor to send message M2 to AnswerActor but there is no reply, only if I add some reply in following(case M1) it could work

case message: M1 => requestMap.put(name -> sender())
    sender() ! something

Is it possible to implement the logic above in akka?


Solution

  • What I suspect, from your limited description, is that M2 is not being received by questionActor after it receives M1 (or at least it's not being received soon enough after for the ask to timeout). In general there is no guarantee that a message sent from actor A to actor B will be received before a message sent from actor C to actor B, regardless of whether C sent the message before or after A (the ordering guarantee is that if actor A sends messages 1 then 2 then 3 to actor B, 3 will not be received before 1 or 2 is received and 2 will not be received before 1 is received).

    In general, it's not a good idea to use Await in an actor or in a stream, since that prevents the actor from processing any message. Within an actor, it's better to use the pipe pattern:

    import akka.pattern.pipe
    
    (questionActor ? M1).pipeTo(context.self)
    

    If you wanted to ignore (or stash) every message besides MyReply, you could then immediately use context.become to install a new message handler which ignores/stashes as desired.

    Within a stream, it's generally best to use the mapAsync or, in some cases (Akka 2.6.x only) ask stream stage to perform the ask in a non-blocking way.

    The use of Await.result may also directly be causing your problem, depending on how many cores/vCPUs are available and the Akka version: the blocking may prevent any actor or stream stage from getting CPU time.