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?
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.