From start to stop
In the previous post we saw the different ways in which actors can communicate with each other. In this post we’ll see the lifecycle of an actor.
The Actor Lifecycle
The lifecycle of an actor begins when the actorOf( ) method is called either by the system or by the context. This results in the creation of an incarnation of the actor defined by the Props passed to actorOf( ).
This incarnation is then put into its place. The place that this actor will occupy is identified by the path of the actor within the system and a UID.
Why do we keep using the word “incarnation” to refer to an instance of the actor? Well, because we can have multiple actors of the same type running within the system. For example, we can have multiple GreetingsActor within the system and each instance is an incarnation of the source code.
As shown in the diagram, a restart (caused by an exception in the actor) only causes the instance backing the incarnation to be swapped out; the UID remains unchanged. The UID is only changed when the actor incarnation is fully stopped and a new incarnation takes its place.
Once the incarnation is put in place, the actor’s preStart( ) method is called. This is the place where you’d acquire any resources you might need like database connections, files, etc.
For the sake of completeness, there’s one more place where you might perform the initialisation — the constructor of the actor.
preRestart( ) and postRestart( )
The preRestart( ) and postRestart( ) methods help us handle what happens in case an actor fails and is restarted for some reason.
When an actor is crashing, it’s preRestart( ) method is called. This is the place where you’d release all the acquired resources and perform any other cleanup operations you need to perform. The default implementation terminates all the children and calls the postStop( ) method.
Now we need a new actor to take the place of the crashing actor. The actorOf( ) method is then called to produce a new instance.
Then, the new instance’s postRestart( ) is called. The default implementation of postRestart( ) calls preRestart( ).
Since this is a restart, the processing of the mailbox resumes from where it left off minus the message that triggered the restart; that message will not be processed again.
The last method in the lifecycle of an actor is the postStop( ). Once this method is called, the actor will stop receiving any new messages and the current messages will be redirected to dead letter mailbox.
Now that we’ve seen all the life cycle methods, let’s modify the GreetingsActor to print out the different stages.
When you run the code again, you’ll be able to see the logs from preStart( ) and postStop( ).
That’s it for this post.