Akka Typed: Stateful and Stateless Actors | Rock the JVM

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome back boys and girls this is daniel for rock the jvm and in this video we are going to be talking about akka typed actors and in particular we're going to discuss actors state now this video is for people getting started with archetyped actors so we'll look at how we can keep state inside of an actor in a few different ways now this video assumes that you know some of the principles of actors now in short standard multi-threaded or parallel applications are a general pain in the neck to write because of concurrency issues so managing threads is a pain in the neck most of the time so in aqua we design applications in terms of these computational entities that we call actors which are fully encapsulated objects whose state we cannot really access directly but we can only interact with an actor via an asynchronous message exchange now message passing and handling eliminates the need for us to manage threads and concurrency while making it easy to write massively distributed systems so no logs needed so no general concurrency issues now i'm going to write some code in this video so as always i recommend that you code with me and whenever you need to refresh your memory on these topics and techniques i'm about to write just refer back to this video or to its written form on the blog with the link in the description now for this video i'm going to start a new application so i have an object here in my development environment which i recommend that you do as well and for this video i'm going to use the akka 2.6 typed version of the library so if you go to your build.sbt you will see here or you will need to add your own akka version so i'm going to add a 2.6 version of the library you can choose any patch version you like i think at the moment of this recording akka has reached 2610 or something like that and you will need to add this line over here com type save aka percent percent aqua actor typed and then insert your favorite aqua version in your library dependencies and then reload your sbt dependencies to install the library now if you need some more time you can pause the video to do that but assuming that you have your aqua library already installed and running you can also by the way you can find these library dependencies on the blog article then i'm going to get back to my actual code and i'm going to start a main method just in case we need to test something and for this example we will write an actor that reacts to external messages from the world by changing its happiness level originally starting at zero so for this example i'm going to define a bunch of messages starting with a trait that i'm going to call simple thing like the simple things in life like eating chocolate or doing some sort of chore and so on and so forth that might increase or decrease this actor's internal happiness so i'm going to create a case object i'm going to call eat chocolate which extends this simple thing i'm going to create a case object let's call this wash dishes or some kind of chore which extends simple thing and i'm going to add another case object just for the sake of variety i'm going to say learn aka which i'm expecting will bump your happiness level by a lot so i'm going to extend simple thing as well and i'm going to define this actor with a mutable piece of data also known as state by defining its behavior so you know that in archetype actors are defined or described by their behavior so i'm going to define a value that i'm going to call emotional mutable actor mutable in the sense that it can store a mutable state and this is of type behavior and i'm going to import behavior from aqua actor type so i'm going to say behavior of simple thing and the simple thing is the type of messages that this actor is allowed to receive and i'm going to use the construct to set up this actor i'm going to say behavior is plural so i'm going to type it like this and then i'm going to click option enter or alt enter on windows and i'm going to import behaviors from the scala dsl package so behaviors is an object that has a bunch of factory methods that will spawn behaviors for us i'm going to use behaviors.setup and behaviors.setup takes a function from an actor context and then here we will need to spin up the actor state or we can spawn child actors and so on and so forth and at the very end of this lambda we will need to return the behavior of the actor so i'm going to create this actor state with a simple variable so i'm going to define a var happiness starting at 0. now the end result of this lambda is going to be another behavior so i'm going to use another construct from this behaviors object so i'm going to say behaviorals plural dot receive message and receive message as you may have already read from the akka basics receive message takes a function that takes an argument of type t in this case simple thing and then returns the new behavior that the actor will have after processing that individual message so i'm going to use a receive message and i'm going to inject a partial function inside to handle all the cases so i'm going to say case eat chocolate and as a reaction to eat chocolate i'm going to log something so that we can see our data in the console so i'm going to say context log info and i'm going to write something like i'm going to inject my happiness here so that we can keep track of it eating chocolate getting a shot of dopamine all right and i'm going to mutate my happiness variable so i'm going to say happiness plus equals one and then to keep my same behavior i'm going to return behaviors plural dot same behaviors.same is a way to keep the exact same behavior to the next message that this actor will receive and i'm going to basically duplicate these cases to the other message types that the actor might support so in case we get for example wash dishes i'm going to print my happiness and i'm going to print something else like doing a chore womp womp and i'm going to decrease my happiness for example by two and i'm going to keep the same behavior and in case i get learn alca i'm going to print the same happiness and i'm going to say learning aka this is cool or something and i'm going to expect that your happiness just bumps up by a huge value like a hundred and in case i receive anything else just to be super sure i'm going to do a very similar thing i'm going to copy most of this stuff i'm not going to mutate my happiness but i'm going to keep the same behavior and the message is going to be something like received something i don't know all right so this actor can treat every individual message differently but whatever it does it will keep the same behavior and it will mutate its happiness according to the kind of message that it receives so this is not really rocket science now if we wanted to test this actor all we have to do is back this behavior by an actual actor system and then fire a few message to the actor that is the root guardian of the system so i'm going to define an actor system in my main so i'm going to say i'm going to define a vowel let's call this emotional actor system as actor system and you need to import actor system from actor type so make sure you use the right actor system and i'm going to pass in this behavior so i'm going to say emotional mutable actor and i'm going to give this system a name let's call this emotional system now this actor system can interact via messages with or we can interact with it via messages because it also contains its root actor and i'm going to say emotional actor system tell for example eat chocolate and i'm going to send a bunch of messages so i'm going to say emotional actor system eat chocolate a few times let's send a wash dishes and let's also send a learn aka and at the end i'm going to say after system terminate to make sure that the resources are released gracefully so i'm going to in inject a an artificial thread sleep to make sure that all the messages have been properly set and then i'm going to say emotional actor system terminate now in production you would not use thread sleep to terminate this actor system you would terminate via some sort of an external call or call back all right but in this very simple test i'm going to simply wait a second and just terminate the actor system now i'm going to right click and run this application to see the log lines that we get so i'm going to right click and run the compiler and then i'm going to see some log lines in my console and after a second the application terminated now a word of warning if you don't see these log lines or blog lines that look like this in your own console it means that you haven't properly set up your log appender and akka needs some special configurations to do that you don't need to concern yourself with that that will distract from the goal of this video instead if you don't see log lines to your console instead of context log info just use print line all right so use print line to simply show these strings to the console now let's inspect the log lines i'm only concerned with the actual strings so notice that the actor started at happiness zero eating chocolate and then with the next message its happiness turned to one and then the next message happiness turned to two and then after the the third eating chocolate the happiness turned to three and after the chore happiness dropped back to one so this is the value of the happiness before the effect of that particular message and after this message after learning aka i'm pretty sure the happiness of this actor just jumped to 101. so in short this is how we can make a very stateful actor by using the contra and the construct behaviors.setup and given an actor context we have the scope of this lambda to spin up some initial stuff that will get created when the actor is properly allocated by the actor system and then this behavior will be assigned to this actor and ready to accept messages so in here we have the opportunity to define variables or other mutable states this is why we named this actor emotional mutable actor now in pure scala we basically hate variables and just about anything mutable so in this part i'm going to show you how we can write the exact same actor without needing a variable so instead of a variable we will use a method that will take an int argument and return a behavior instead so here's what i'm going to do i'm going to define a method this time around so i'm going to say def i'm going to define let's call this emotional functional actor and instead of having a variable i'm going to put every single variable that i have in my mutable state and i'm going to transform those into method arguments so i'm going to name this happiness as an int starting at 0. and the return value of this method is going to be a behavior object so i'm going to say behavior singular wove simple a simple thing and because i'm not going to use a variable anymore so i do not need to start anything before the actor is ready to receive messages i'm not going to use the construct behaviors.setup this happens most of the time so when you want to change an actor behavior from being stateful to being stateless in terms of what i'm doing here you probably will not need to do behaviors dot setup that's basically most of the time but i'm going to say behaviors dot receive and the receive takes a function that that takes two arguments the context and the message being received so i'm gonna say receive and i'm going to use the curly brace syntax again and i'm gonna say context and message and then i'm going to do basically the same pattern match on the message so i'm going to copy all these cases and then i'm going to say message match and then i'm going to paste the cases inside now notice that once you paste the cases the logic basically states this stays the same and the compiler gives you the warnings of mutating the initial the original mutable state but in this case you have a method argument and so you can change it rather instead of changing the the previous variable and returning the same behavior you will need to return a new behavior and so i'm going to call this emotional functional actor method again with a new value of my happiness i'm going to say happiness plus one and i'm going to do the same for the other cases so emotional functional actor with happiness minus two and here i'm going to say emotional functional actor with happiness plus 100. so the point is that the actor that is backed by this behavior upon receiving a message the message will run through this pattern match and assuming this message is for example an e-chocolate we will do the logging thing and the behavior that this actor will be for the next message is going to be the object returned by this new call and so this will be the new behavior and this new behavior will be applied at every case so we will call this method again for every case with the appropriate new argument this is the technique that i wanted to show in this video how to turn an actor from stateful with variables to stateless in the sense that every piece of stateful or mutable information you now pass as method arguments in the form of immutable values and whenever you need to mutate your state instead you create a new behavior by calling this method again with a new value for that particular argument and sure enough if we go test this new actor instead of emotional mutable actor i'm going to use emotional functional actor and i don't even need to pass an argument here because my happiness starts at a default value of zero i will right click and run my application and i will expect basically the same log lines so look at that we have eating chocolate getting a shot of dopamine three times with happiness zero one and two and then doing a chore from happiness three it drops to one and then learning aka this is cool so basically the same log lines so the steps to turn a stateful actor into stateless would be to turn your actor behavior as a method this is this will be the first step and the arguments of the method will be immutable versions of the pieces of data that you use to hold and the second piece is that if you created your stateful actor with behaviors.setup which was necessary for you to initialize your immutable state you'll now know problem probably no longer need it and so in this case i use behaviors receive or even behaviors.receive message which only takes a message as an argument now most of the time stateful actors will keep the same behavior after the reception of a message and if you look at the previous example we simply mutated the state and then always return behaviors that same because we never actually need to change our behavior now in this case with every message reception you'll change the behavior to a new method call with the new arguments depending on the data that you need to change and in this case we change the happiness counter now you may be wondering whether calling this method again in this message handler so we're basically calling this method from within its own definition you might be wondering whether this is a recursive calling can blow up the stack if you receive too many messages now this is an interesting topic now this so-called recursive call is detected by the compiler because you're calling the same method from within its own definition this is not actually truly recursive and the reason is the following when a thread schedules this actor for execution it will dq messages off its own mailbox now once it handles a message it will create a new behavior which is a new call of this method or whatever your method is but this method returns immediately with a new behavior object so this method returns a new behavior it doesn't call itself forever or recursively so the thread will simply apply this new returned object to the actor so that when the actor is scheduled again for execution and it handles the next message that particular object will be the handler of the message so this is not a true recursive call so in the process of transforming a stateful actor into into a stateless one do not be afraid to call the same method at any time in your message handler alright so i hope this was useful you learned how to define state inside of an actor and how to turn it into a functional stateless actor with aqua typed actors if you like this video go ahead and click the like button for me and subscribe to the channel for more videos like this and give me feedback in the comments i read every single one and follow me on twitter and linkedin for fresh updates on upcoming material and also check out the rock the jvm website we have tons of material like this on scala and functional programming and akka as well until next time i'm daniel signing off you
Info
Channel: Rock the JVM
Views: 2,343
Rating: 5 out of 5
Keywords:
Id: gwZjdRQTPu8
Channel Id: undefined
Length: 19min 10sec (1150 seconds)
Published: Mon Oct 26 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.