Elixir tutorial Part 3 (GenServer and Supervisor)
Key Takeaways
This video tutorial demonstrates how to use Elixir's GenServer and Supervisor to create a basic calculator API, covering topics such as process management, supervision, and restarting processes. The tutorial utilizes tools like Elixir, OTP, Erlang, and Mix to create a detached process and manage its state.
Full Transcript
hi guys welcome to Elixir tutorial part three my name is tensor from the tensor programming blog So today we're going to build a toy chat application and we're going to use this application to demonstrate what gen server is and what supervisors are so gen server and supervisor are both modules that were supplied by erang and the OTP which comes with erlang OTP stands for open Telecom platform earling was originally written for tele phone stuff like telephone switchboards but this is still pertinent to servers and other things especially in networking and distributed systems all right so let's create our file we're going to say mix new chat and this will create a chat folder with us with the basic skeleton of our Elixir file let's open it up in Sublime Text so here's our chat program and we want to create a new file inside the lib folder our new file will be called server. ex and inside of it we want to say def module chat. server so this module is going to use gen server so we're actually going to say use gen server now what gen server is is a it's basically just an abstraction with a set of special functions that help us Define how we can create detached processes that take on module functionality so like our calculator app used a loop function to iterate through and to identify the messages that we were sending it gen server makes this process a lot easier to create a basic gen server module you want to create a simple function called start link and the start link function will invoke gen server. start link and inside of this start link function you'll pass in the module name and then the initial state that you want to set we can actually replace This chat. Server right here with an atom called module and this is an Elixir thing so this is just a nice little piece of syntactic sugar that we can use basically what this is saying is it's saying okay take the chat. server module and spin up a process with all the attributes of it you have to remember that with Elixir programming is mainly just talking to and from processes so with the start link function we need to create a quote unquote response that comes from the processes side so if you think of it like uh client and server so for example this start link function will start on the client side and then our next function will start on the server side or it will be what is called a call back function to respond to start link we're going to create a function called init and this init function will take in our state so we're going to call our state messages and then in it will just return a tuple of okay and then the messages when we invoke start link it will spin up a process and it will return a tuple of okay and then the process ID and then this init function will fire and it will set the state inside of the proc process so now we want to be able to actually get the state from our process so we're going to create a function called get messages and in here we just need to pass the process ID and we're just going to call gen server. call this is going to take in the process ID and then a little atom called get messages and then on the server side we want to have another function which is called handle call and this is going to take in the get messages atom first and then it's going to have a variable called from and we're putting an underscore before this because we're not going to actually use it inside of the function at least not directly and then we want to pass our state inside of here as well we're going to create a tuple in here it's just going to say reply it's going to have the state twice afterwards we want to get the state from our process so we pass in the process ID to this function and then gen server calls that process and sends this message to the process then the process fires this handle call function and it takes in the atom so it basically does a pattern match of these two atoms then it uses this from call to identify where the uh message is actually being passed from in our case it' be coming from the IEX process and it's using this the messages state to account for whether or not we're changing the state of the uh function in this function which we're not and then the reply here has the response state so the state that we're going to see as a response and then the new state in this case it's going to be the same value because we're not actually changing the state in this function but in some other cases it it's not uncommon to actually create multiple States so gen server call is actually mostly used for setting and getting state so this is important because the Gen server. call function is actually a synchronous call so it's not concurrent if we do not get this handle call function to call back it will actually stop running the code so it's a block call so we generally use the Gen server call we want something that we need a direct response for in this case getting the state is the reason why we used a non-concurrent function this is not very interesting because we're just passing back and forth an empty linked list so let's create a function that allows us to modify that linked list so we're creating a function called add message we passing in the process ID and then of course the message that we want to add to the list this is going to call gen server. cast instead of call and inside of this we're going to pass in the P ID and then a tuple of add message as an atom and then the message that we want to actually pass into the state then we're going to create a handle cast function now handle cast needs the add message so the atom that we've created here needs to be in our handle cast function in the beginning of the tupol and then we want to have the message that we're passing back into here so the new piece of state that we're passing in here and this is actually our message without an ass so MSG and then we also want to pass in all of the states so the entire link list so msgs and then in this case we're going to actually return a tuple of no reply and then we're going to take our link list and cons the message onto the messages so basically we're putting the message that we're that we wanted to add to our list in the front of our list all right so this is a completed gen server module so let's run inside of I ex and take a look at what we've got so we run i-s miix and this will compile our two files and then generate the chat app to actually start up the process we call chat. server. start link and this will actually return our process ID and an okay Tuple so we also we want to bind that process ID to P ID so we're going to call it again and we're going to start a link so now we have it bound to our process ID so now we can run our other functions as well we can say check server. get messages and we can invoke it with just calling the P ID on it and as you can see this returns back a empty list now we can set a message in here so say we want to put hello in here we just pass the P ID and then the string of hello and of course my mistake it's not called set message it's called add message and there we go see it returns just a little atom that says okay and that's because this cast here is actually a asynchronous c so it's not a blocking call and generally we use it not because we do not actually need a response in this case so all we're doing is changing the state we do not want a response we just want it to tell us that this function did in fact run but we don't need it to show us what the state looks like so let's add something else so for example how are you and then let's get the state back so we're going to call get messages again and as you can see how are you is before hello inside of this new list and we've added state to our list all right so now let's create a supervisor so we're going to create a new file here this file is going to be called supervisor. ex and our module is going to be called chat. supervisor and like gen server we just call use supervisor to add the supervisor properties to our module supervisors are important because they allow us to create processes which watch our processes and then if what say our process dies for example say our chat process just goes go down our supervisor will try to restart it so in here we need to create a start link function and in here we're going to call supervisor. start link and this is going to look very much like our gen server start link so we're just going to pass in that atom of module as well as an empty list and the empty list is sort of the state of this supervisor as well we're also going to create an init function but in this case we don't need to actually know what the state is because we're going to create our own State inside of this so we're going to create a variable called children and our children variable is going to take in a list and this list is going to have a function inside of it called worker and this will Define our chat server as our worker and it will also pass in the initial state of that chat server we want this module here to be the worker that we're looking at with this supervisor now to actually make the supervisor look at this chat server module we're just going to call the supervise method and inside of it we're going to pass that children variable that we created and then we're going to pass the strategy that we want it to use and in this case we want it to use 14 one now this strategy basically means that if one of our processes dies the supervisor will automatically try to spin it up so if we had multiple processes if one dies it won't affect the other ones then this will try to spin up the dead process of course we have multiple different strategies that we could use there is a strategy called one for all and what that will do is if one of the processes dies it will try it will basically restart all of the processes that it's overlooking and then there's another one called rest for one and what will happen is when a process dies it will restart that process and then any process that was activated after it so that's sort of a strategy that's based off of when the processes are started and finally we have another one called simple one for one and this is more of a dynamic way it allows us to Define when we can't want the processes to be reset and so on and so forth so this is not enough so now we need to change our actual server. ex to make this supervisor work the way that we actually change this is we're going to actually come in here and we're going to add another argument to our gen server. start link and this is going to be the name and in this case we just want to associate our process with this chat room atom so rather than passing around a process ID we can just hardcode chat AR room into these other functions so so if we take this and we change the P into chat room then we won't actually have to pass anything to our get message function and we can actually replace the P ID here as well with chat room the downside to doing this however is that we can only have one process of this type because it's being called by a atom instead of a process ID so let's run this inside of our reple so to run everything we want to call our supervisor so we're going to say chat. supervisor start link and this will return with the Tuple and the process ID that it's started on so it's run the init function which set up the children and then supervise the children but it also spawn up the chat. server so we don't actually have to run the chat. server start link function directly if we do it'll fail as you can see here it gives us an error and says it's already been started on this process ID so now we can also just call the get message function and we don't have to pass it anything it'll just give us the state because it knows exactly which process we're referring to and we can add messages we don't even need to use parentheses because it only takes in one argument just say we want to add hello and again how are you doing and we can get those messages back as well we can also use a little function called process where is and then we can type in the chat room atom and this will return the process ID that this process is on and we can use this to actually kill our process so if we want to kill our process we just pipe in the process ID into a function called process. exit and then we pass a kill atom into this and this will kill our process and as you can see it returns a Boolean of true which means that this process was killed however if we check the where is it will actually give us a new process ID because our supervisor automatically rest started the process so of course our state is now different if we get our messages it's now an empty listing again and the reason for that is because we don't have a database to actually back up the data so now that we finish our application let's make it so that this application will automatically run when we run mix so we can say mods and then we pass in a tuple with the chat module namespace so the chat will be our entry point and then we pass in an empty list so we have no uh modifications that we want to make to the chat so now let's set up our chat. EX file so let's delete all this boiler plate that was built into it we want to use the application module and we're going to create a little function just called start and this will pass a variable called type and arguments and inside of this we'll just call chat. supervisor start link so now if we run i-s miix this will compile our file and it will automatically start our application so we don't need to run chat. start fact if we do this will just come back with an error but one of the cool things that we can do due to some of of the tools that come with Elixir is we can actually open up a guey that allows us to look at how our processes are shaped so this is called Observer start and I spelled Observer wrong so here's our guey and as you can see we can go to Applications and it has all the Elixir applications that are currently running so we have mix we have our logger we have a little kernel kernel that's running we have IEX that's running we have Elixir itself and we have our chat application this is taking up three processes and then a process called chat room and we can come in here and we can actually look at all the processes and we can actually kill any of the ones that we want so if we want to kill the chat room we can do that and as you can see even though we've killed it it automatically restarts because of the supervisor anyway guys I hope you enjoyed this tutorial I hope it was sufficiently helpful for Gen server and for supervisor if you like this video then feel free to subscribe and like if you have any questions or comments feel free to comment on the video and if you dislike it then by all means you can downvote us as much as You' like all right guys have a good night
Original Description
In this tutorial, we build a basic calculator API with elixir. We talk about processes and use them to create our calculator.
Github: https://github.com/tensor-programming/elixir-4
Feel free to donate:
BTC: 1ExBSiaEa3pceW98eptJwzR9QHrYZ71Xit
ETH: 0xD210Ea51F1615794A16080A108d2BC5471F60166
Check out our Twitter: https://twitter.com/TensorProgram
Check out our Facebook: https://www.facebook.com/Tensor-Programming-1197847143611799/
Watch on YouTube ↗
(saves to browser)
Sign in to unlock AI tutor explanation · ⚡30
Playlist
Uploads from Tensor Programming · Tensor Programming · 33 of 60
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
▶
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
NodeJs, Text editors and IDEs
Tensor Programming
Vanilla JS todo App
Tensor Programming
Elm Tutorial part 1
Tensor Programming
Elm Lang Tutorial, Part 2
Tensor Programming
Elm Tutorial Part 3
Tensor Programming
Elm Tutorial Part 4 -- Analog Clock App
Tensor Programming
Elm Tutorial part 5 -- Snake Game
Tensor Programming
Elm Tutorial part 6 -- Calculator
Tensor Programming
Go Tutorial part 1 -- Hello World and Static File Server
Tensor Programming
Go Tutorial part 2 -- Web Crawler
Tensor Programming
Go Tutorial Part 3 (Web App part 1)
Tensor Programming
Go tutorial Part 4 (Web tutorial part 2) - Using templates
Tensor Programming
Go tutorial part 5 (web app part 3)
Tensor Programming
Go tutorial part 6 (webapp part 4)
Tensor Programming
Go tutorial part 7 (web app part 5)
Tensor Programming
Go tutorial part 8 (Web app part 6)
Tensor Programming
Go tutorial Part 9 (web tutorial part 7)
Tensor Programming
Go tutorial Part 10 (web app part 8)
Tensor Programming
Go tutorial Part 11 (Web app Part 9)
Tensor Programming
Go Tutorial Part 12 (Web app Part 10)
Tensor Programming
Go Tutorial Part 13 (Web app Part 11)
Tensor Programming
Looking at Elm 0.18
Tensor Programming
Go tutorial Part 14 (Web tutorial part 12)
Tensor Programming
Go tutorial Part 15 (Web tutorial part 13)
Tensor Programming
Go tutorial part 16 (web app part 14)
Tensor Programming
Elm Tutorial Part 7 (SPA part 1)
Tensor Programming
Elm Tutorial Part 8 (SPA Part 2)
Tensor Programming
Electron Elm Tutorial
Tensor Programming
Go tutorial part 17 (web app part 15)
Tensor Programming
Up and Coming Programming Languages and Technologies for 2017
Tensor Programming
elixir tutorial part 1
Tensor Programming
elixir tutorial part 2
Tensor Programming
Elixir tutorial Part 3 (GenServer and Supervisor)
Tensor Programming
Elixir Tutorial Part 4 (GenStage)
Tensor Programming
Elixir Tutorial Part 5 (Plug and Cowboy)
Tensor Programming
Phoenix Framework Tutorial Part 1 (elixir part 6)
Tensor Programming
Phoenix Framework Tutorial Part 2 (elixir part 7)
Tensor Programming
Phoenix Framework Tutorial Part 3 (elixir part 8)
Tensor Programming
A Intro to Clojure and Clojure Syntax
Tensor Programming
An Update about the channel
Tensor Programming
Intro to Rustlang (Setup and Primitives)
Tensor Programming
Intro to Rustlang (Strings, Tuples, Arrays, Slices and Pretty Printing)
Tensor Programming
Intro to Rustlang (Ownership and Borrowing)
Tensor Programming
Intro to Rustlang (Structs, Methods, Functions, Related Functions and the Display/Debug Traits)
Tensor Programming
Intro to Rustlang (Control Flow, Conditionals and Pattern Matching)
Tensor Programming
Intro to RustLang (Enums and Options)
Tensor Programming
Intro to Rustlang (Vectors, HashMaps, Casting, If-Let, While-Let, and the Result Enum)
Tensor Programming
Rustlang Project: Snake Game
Tensor Programming
Intro to Rustlang (Traits and Generic Types)
Tensor Programming
Intro to Rust-lang (Closures, the Box Pointer and Iterators)
Tensor Programming
Intro to Rust-lang (Modules and Lifetimes)
Tensor Programming
Intro to Rust-lang (Macros and Metaprogramming)
Tensor Programming
Intro to Rust-lang (Error Handling)
Tensor Programming
Intro to Rust-lang (Concurrency, Threads, Channels, Mutex and Arc)
Tensor Programming
Intro to Rust-lang (Tests, Attributes, Configuration and Conditional compilation)
Tensor Programming
Rustlang Project: Port Sniffer CLI
Tensor Programming
Rustlang Project: Chat Application
Tensor Programming
Rustlang Project: CLI Toy Blockchain
Tensor Programming
Intro to Rust-lang (Setting up a Development Environment)
Tensor Programming
Intro to Rust-lang (Building a Web API with Iron)
Tensor Programming
More on: LLM Engineering
View skill →
🎓
Tutor Explanation
DeepCamp AI