Search code examples
scalaakkaactor

context.become changes the behaviour of Akka Actor


I'm learning how to use context.become to control the state of my actor, i'm using this code:

class MyActor extends Actor {

  override def receive: Receive = {
     println("Happens here")
     active(Set.empty)
   }

  def active(isInSet: Set[String]): Receive = {
    case Add(key) =>
      context.become(active(isInSet+key))
    case Contains(key) =>
      sender() ! isInSet(key)
    case ShowAll =>
      println(isInSet.toSeq)
  }

}

case class Add(key: String)
case class Contains(key: String)
object ShowAll


object DemoBecome extends App{

override def main(args: Array[String]): Unit = {

 val system = ActorSystem("BecomeUnbecome")
 val act = system.actorOf(Props(classOf[MyActor]), "demoActor")

 act ! Add("1")
 act ! ShowAll
 act ! Add("2")
 act ! ShowAll

 Thread.sleep(10000)
 System.exit(0)

}

When i send the first message, the "receive" works and prints the message, after the second message doesn't show, this is my output:

Happens here
Set()
Vector(1)
Set(1)
Vector(1, 2)

If i change the receive method, for this:

def receive = {
  case a: Add => println("happens here Add" )
  case c: Contains => println("happens here Contains")
  case ShowAll => println("happens here Show")
}

I receive this output:

happens here Add
happens here Show
happens here Add
happens here Show

So i tried, to track the moment when "receive" is "blocked", but i didn't have success, my doubt is: When i uses context.become in my actor, how and when Akka handle the messages after the first one?


Solution

  • When you use context.become you are changing the behavior in your actor. That means, when the actor starts it using the default receive behavior. However, when it receives a message it prints the message Happens here and uses the partial function active to handle it.

    Since, inside active you call context.become(active(_)) the behavior of the actor changes. From now on, when a messages gets sent to the actor it will execute the partial function active instead of the receive method and that's why you are not seeing Happens here more than once in your output.