Combining behaviors

Now that we have defined every worker in the bakery, it is time to finally get us a Manager. In Chapter 11, An Introduction to the Akka and Actor Models, we implemented a Manager using the FSM library. In Akka Typed, we can achieve the same effect without any libraries just by defining atomic behaviors for each state and then returning the appropriate behavior as required:

def waitingForGroceries = receiveMessagePartial[Command] {
case ReceiveGroceries(g) =>
context.log.info("Mixing {}", g)
chef ! Chef.Mix(g, context.self)
waitingForPastry
}
def waitingForPastry = receiveMessagePartial[Command] {
case ReceivePastry(p) =>
context.log.info("Forming {}", p)
cook ! Cook.FormCookies(p, context.self)
waitingForRawCookies
}
...

Here, we have defined two behaviors, and each of them expects a specific message type, performs the required message passing to the managed actors, and returns the next behavior in the chain. This way, it is possible to model the serial behavior we implemented with untyped Akka. 

However, we can do better. Akka Typed allows us to combine behaviors so that we can implement a parallel version of the Manager by chaining behaviors together and returning the combined behavior from every atomic behavior we define:

def manage(chef: ActorRef[Chef.Command],
cook: ActorRef[Cook.FormCookies],
baker: ActorRef[Baker.Command]): Behavior[Command] =
...
def sendBoyShopping = receiveMessagePartial ...
def waitingForGroceries = receivePartial[Command] {
...
manage(chef, cook, baker)
}
def waitingForPastry = receiveMessagePartial[Command] {
...
manage(chef, cook, baker)
}
def waitingForRawCookies = receiveMessagePartial[Command] {
case ReceiveRawCookies(c) =>
baker ! Baker.BakeCookies(c, context.self)
manage(chef, cook, baker)
}
def waitingForReadyCookies = receiveMessagePartial[Command] {
case ReceiveReadyCookies(c) =>
context.log.info("Done baking cookies: {}", c)
manage(chef, cook, baker)
}

lookupSeller orElse
sendBoyShopping orElse
waitingForGroceries orElse
waitingForPastry orElse
waitingForRawCookies orElse
waitingForReadyCookies
}

Here, the manage constructor is used to define atomic behaviors for each message type the Manager is supposed to be able to handle. Then, the existing behaviors are combined into one. This makes our Manager capable of processing every message in any processing state.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.125.51