Friday, July 3, 2020

Akka Typed Notes

<draft>
Traditionally Actors have "recieve" method which handles the protocol messages and unhandled messages are taken care by other "unhandled" method. This has a drawback on evolution of protocols. This means that if someone adding a new protocol message then handling of that new message should be done together.Otherwise new message will endup with unhandled messages. Hence its error prone. Typed actor are designed to remove this limitation and designed to be "Protocol first".

Protocol first: means that you do not have to worry about the variety of protocol messages that recieve method can recieve. The intent of Akka Typed is not merely to make sure that messages get declared in a structured way and to ensure that a few unhandled messages aren’t missed.

Actors are defined in term of Behavior, which has two main tasks. Namely process the current message and also indicate what should be behavior for the next message. Second task is done by returning next behavior. If there is no change in behavior it can return itself.

Few implementation differences: Type parameter is invaded to types ActorRef, ActorContext and ActorSystem.There is no implicit sender stored in AbstractBehaviour.
ActorRef is now typed which means actor can specify which type of messages it can receive. 
"Signal" message type signifies the change in the lifecycle of an actor. There are no predefined callback method invoked on actor lifecycle change.

Behaviour Factories: 1.Behaviors.recievemessage[T] gives the template to define the Behaviors.
2.Behaviors.receive[T] is same as recievemessage but additionally provide ActorContext object alongwith message. Context usually allows us to create new child actor.
3.Behaviors.same is returned when we want to have same behavior for next message as well.
 Behaviors.empty,  and Behaviors.ignore are to signify.....????.
4. Behavior.unhandled goes to dead letter inbox and have similar behavior related to unhandled function in classic Akka.
5.To stop an actor, it can return Behavior.stopped after work is done.
6.Best way to start the system is to put initialization code in a gaurdian's behavior. "Behavior.setup" help us in achieve that it takes guardian's behavior and name of the system. It runs the initialization function which will be supplied with context upon receive of first message. And then return the behavior to be applied to first message. The factory function in setup is passed the ActorContext as parameter and that can for example be used for spawning child actors.

7."Behaviors.receiveSignal" is used to receive the signal messages which in turn received by an actor if it is watching some other actor using context.watch method. To observe different stages of lifecycle of an actor (called signal). An actor can register to observe signal by providing PartialFunction[(ActorContext[T], Signal), Behavior[T]] by calling "Behaviors.recieveSignal" method. Signal enum have values like PreRestart, PostStop and Terminated etc.
7.Behavior.withTimers give access to timerSchedular through which an actor can schedule some messages.

StashBuffer allows an actor to temporarily store the messages till actor change its behavior to the messages intended behavior. Too many messages can cause stashoverflow exception so choose capacity carefully.

ActorConext's spawnAnonymous and spawn methods allow to create new child actor. Both methods have overloaded methods which takes additional dispatcher argument.Typed akka dispatcher is only configurable through setting key "akka.actor.default-dispatcher".It also have "watch" method through which an actor can observe other actor life signals or have a death pact with other actor. An alternative to watch is "watchWith", which allows specifying a custom message instead of the Terminated. This is often preferred over using watch and the Terminated signal because additional information can be included in the message that can be used later when receiving it. context provides "log" object. Many of the methods in ActorContext are not thread-safe and
1. Must not be accessed by threads from scala.concurrent.Future callbacks.
2. Must not be shared between several actor instances.
3. Must only be used in the ordinary actor message processing thread.

SpawningProtocol is predefined behavior, defined for creating new actor at each ask or tell call.

ActorSystem's apply method takes the root gaurdian actor behavior and name. When "ActorSystem.terminate" is invoked then the coordinated shutdown process will stop actors and services in a specific order.

Typed akka cluster has a system level actor called "receptionist" which takes the following command 1.find 2.subscribe 3.register. Through receptionist one actor can discover other actor []

MessageAdapter ???

Behavior.validateAsInitial : validate behavior is a legitimate as Behavior.same and Behavior.unhandled should not be initial behavior.


Supervision: An actor can stop itself or get destroyed when its parents dies. A child actor can be forced to stop after it finishes processing its current message by using the stop method of the ActorContext from the parent actor. Only child actors can be stopped in that way. Default supervision strategy of Typed actor is to stop itself in case of any failure or exception. To use different strategy for different kind of exeption use : Behaviors.supervise(<behavior>).onFailure[<ExceptionType>](SupervisorStrategy.Stop|Resume|Restart)


Problem statement : An actor have to speak two protocols.
solution 1: Use Message adapter to convert from one protocol receiver to another. "ActorContext.messageAdapter" method can be used. scala case classes to wrap foriegn protocol messages to actor own message protocol. Message adapter can be implemented using case classes wrapper where new protocol message can be wrapping second protocol message. As case classes apply/unapply function can be levaraged between to and fro between two protocol messages.
Solution 2: Use child actor to speak second protocol.But in this case also the new protocol between child and parent actor is required. Usually representing success/failure/exceptional message. Child is needed to be death watched. Spawning of child and sending it as a receiving actor for second protocol.

Problem statement: Defer the messages till the actor is ready.
Solution: To use stash till actor is ready.

Test a actor: Due to asynchronity of an actor the test can be false negative. Which means that the actor not able to send reply in a arbitrary time limit set by the test but it did send the reply. Instead Typed actor can be tested by checking returned behavior for next message. Since the reply will be synchronus test will become more deterministic.
BehaviorTestkit allows us to test a typed actor. It is a passive actor which means sending a message to behaviorTestkit.ref will not processed immediately.To process the message we should called runOne() method on it explicitly.It also has other method to verify the actor behavior like isAlive() for checking the actor is still alive.TestInbox is another such class representing an actor Ref that can act as sink. It also provide the test context that actor under test used to spawn child actor or invoke death watch etc. This test context will helps in verification of various activities actor supposed to perform.
BehaviorTestKit.getChildKit(parentActorRef) gives the child actor ref which can be further tested using above methodologies.


S<T
called with ActorRef[T]
captured in ActorRef[S]

No comments:

Post a Comment

Statistics Notes

Statistics Measuring center of dataset : 1. Mean is sensitive to outliers its beneficial to use mean if dataset member are close to eac...