This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 13.11, “How to switch between different Akka Actor states with become”.
Problem
In a Scala application, uou want a simple mechanism to allow an Akka actor to switch between the different states it can be in at different times.
Solution
Use the Akka “become” approach. To do this, first define the different possible states the actor can be in. Then, in the actor’s receive method, switch between the different states based on the messages it receives.
The following example shows how the actor named DavidBanner might switch between its normalState and its angryState (when he becomes The Hulk):
package actortests.becometest
import akka.actor._
case object ActNormalMessage
case object TryToFindSolution
case object BadGuysMakeMeAngry
class DavidBanner extends Actor {
import context._
def angryState: Receive = {
case ActNormalMessage =>
println("Phew, I'm back to being David.")
become(normalState)
}
def normalState: Receive = {
case TryToFindSolution =>
println("Looking for solution to my problem ...")
case BadGuysMakeMeAngry =>
println("I'm getting angry...")
become(angryState)
}
def receive = {
case BadGuysMakeMeAngry => become(angryState)
case ActNormalMessage => become(normalState)
}
}
object BecomeHulkExample extends App {
val system = ActorSystem("BecomeHulkExample")
val davidBanner = system.actorOf(Props[DavidBanner], name = "DavidBanner")
davidBanner ! ActNormalMessage // init to normalState
davidBanner ! TryToFindSolution
davidBanner ! BadGuysMakeMeAngry
Thread.sleep(1000)
davidBanner ! ActNormalMessage
system.shutdown
}
Here’s a description of the code:
- The
davidBanneractor instance is created as shown in previous recipes. - The
davidBannerinstance is sent theActNormalMessageto set an initial state. - After sending
davidBanneraTryToFindSolutionmessage, it sends aBadGuysMakeMeAngrymessage. - When
davidBannerreceives theBadGuysMakeMeAngrymessage, it usesbecometo switch to theangryState. - In the
angryStatethe only messagedavidBannercan process is theActNormalMessage. (In the real world, er, entertainment world, it should be programmed to receive other messages, likeSmashThings.) - When
davidBannerreceives the finalActNormalMessage, it switches back to thenormalState, again using thebecomemethod.
| this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |
Discussion
As shown, the general recipe for using the become approach to switch between different possible states is:
- Define the different possible states, such as the
normalStateandangryState. - Define the
receivemethod in the actor to switch to the different states based on the messages it can receive. As shown in the example, this is handled with amatchexpression.
It’s important to note that the different states can only receive the messages they’re programmed for, and those messages can be different in the different states. For instance, the normalState responds to the messages TryToFindSolution and BadGuysMakeMeAngry, but the angryState can only respond to the ActNormalMessage.