Search code examples
scalaakkaactor

akka unstashAll() not replaying the messages


I have this:

val receive = beforeLoadReceive // my default receive

override def preStart(): Unit = {
  doSomeLoadFromDB()
  unstashAll()
  context.become(connectedReceive)
  println("I also get to here..."
}

def connectedReceive: Receive = {
    case GetData =>
      println("for some reason i'm not getting to here after unstashAll why?")
      sender() ! "this is your data"
}

def beforeLoadReceive: Receive = {
    case GetData =>
      println(s"I get to here so it's stashed")
      stash()
}

so i'm using the stash() I see I get a message to there so its stashed, also I see afterwards that unstashAll() is called but I don't get the message in: connectedReceive any reason for that?


Solution

  • I'd recommend moving DB initialization and unstash/become code to a separate message (say InitDB) handler as preStart() is called before any message is processed. The code below works as expected:

    object GetData
    object InitDB
    
    class ReporterActor extends Actor {
      val dbActor = context.system.actorOf(Props(new DbActor()))
    
      override def preStart(): Unit = {
        super.preStart()
        dbActor ! GetData
      }
    
      def receive = {
        case m: String => {
          println("Received: " + m)
          context.system.terminate()
        }
      }
    }
    
    class DbActor extends Actor with Stash {
      val receive = beforeLoadReceive // my default receive
    
      override def preStart(): Unit = {
        self ! InitDB
      }
    
      def connectedReceive: Receive = {
        case GetData =>
          println("for some reason i'm not getting to here after unstashAll why?")
          sender() ! "this is your data"
      }
    
      def beforeLoadReceive: Receive = {
        case InitDB =>
          // doSomeLoadFromDB()
          Thread.sleep(5000)
          context.become(connectedReceive)
          unstashAll()
          println("I also get to here...")
    
        case GetData =>
          println(s"I get to here so it's stashed")
          stash()
      }
    }
    
    val as = ActorSystem()
    val actor = as.actorOf(Props(new ReporterActor()))
    
    Await.result(as.whenTerminated, 10.seconds)
    

    Output:

    I get to here so it's stashed
    I also get to here...
    for some reason i'm not getting to here after unstashAll why?
    Received: this is your data