Supervisor And GenServer Drills
Mix.install([
{:jason, "~> 1.4"},
{:kino, "~> 0.9", override: true},
{:youtube, github: "brooklinjazz/youtube"},
{:hidden_cell, github: "brooklinjazz/hidden_cell"}
])
Navigation
Home Report An Issue Supervised Mix Projects Games: Supervisor SetupDrills
Drills help you develop familiarity and muscle memory with syntax through repeated exercises. Unlike usual problems, Drills are not intended to develop problem solving skills, they are purely for developing comfort and speed.
This set of drills is for Supervisors and GenServers and using them with Supervised Mix Projects.
A GenServer is a process like any other Elixir process and it can be used to keep state, execute code asynchronously and so on. The advantage of using a generic server process (GenServer) implemented using this module is that it will have a standard set of interface functions and include functionality for tracing and error reporting. It will also fit into a supervision tree.
A supervisor is a process which supervises other processes, which we refer to as child processes. Supervisors are used to build a hierarchical process structure called a supervision tree. Supervision trees provide fault-tolerance and encapsulate how our applications start and shutdown.
GenServer
Create a Zero Genserver that does nothing other than store the integer 0 in its state. Use GenServer.start_link/3 to start the Zero process. Use :sys.get_state/1 to view the state of your Zero process.
Use GenServer.start_link/3 to start your Zero GenServer as a named process.
Create a SimpleCounter GenServer whose state starts as 0. Implement a GenServer.handle_call/3 callback function which accepts the :increment message and increments the state by 1 and returns :ok.
Use GenServer.start_link/3 and GenServer.call/3 to spawn a SimpleCounter process and send it an :increment message.
Use :sys.get_state/1 to see that the state of the counter has incremented.
Create an InitialState GenServer whose initial state can be configured. Call GenServer.start_link/3 to spawn a State GenServer with an initial state. Use :sys.get_state/1 to confirm the state matches your configured state.
Create a State module.
It should:
-
Define a
State.get/1function that uses GenServer.call/3 and a GenServer.handle_call/3 callback function to retrieve state. -
Define a
State.set/2function that uses GenServer.cast/2 and a GenServer.handle_cast/2 callback function to update state. -
Define a
State.start_link/3function with a GenServer.init/1 callback function to initialize the GenServer with a configurable state.
Manually test each function (State.set/2, State.get/1 and State.start_link/3) to confirm they work as expected.
Create a minimal Named GenServer that can be started and configured as a named process using Named.start_link/1. Start a Named process and use GenServer.whereis/1 and/or Process.whereis/1 to find the pid of the named process.
Create a minimal NamedState GenServer that can be started and configured as a named process with a configurable state using NamedState.start_link. Use :sys.get_state/1 to confirm the initial state is as expected and GenServer.whereis/1 and/or Process.whereis/1 to find the pid of the named process.
Supervisor
We’ve created a Worker GenServer for you to use with the following Supervisor drills.
defmodule Worker do
use GenServer
def start_link(state, opts \\ []) do
GenServer.start_link(__MODULE__, state, opts)
end
def init(state) do
{:ok, state}
end
end
Use Supervisor.start_link/3 to start a supervisor process with no children. Use Supervisor.which_children/1 to see the empty list of children.
Example Solution We often bind `children` to a variable in demonstrations. ```elixir children = [] Supervisor.start_link(children, strategy: :one_for_one) ``` But that's not enforced, just idiomatic. ```elixir Supervisor.start_link([], strategy: :one_for_one) ```
Use Supervisor.start_link/3 function to start a supervisor with the Worker as a child using the map syntax.
Use Supervisor.start_link/3 function to start a supervisor three Worker children using the map syntax.
Use Supervisor.start_link/3 function to start a supervisor with the Worker as a child using the tuple syntax.
Use Supervisor.start_link/3 function to start a supervisor with the Worker as a child using the map syntax to start the Worker process as a named process.
Usually worker GenServers should define a start_link/1 function to start under a supervision tree. However, this is idiomatic and we can (but usually shouldn’t) break this rule.
Start the following NonIdiomatic GenServer under a supervision tree using the starter/3 function.
defmodule NonIdiomatic do
use GenServer
def starter(_arg1, _arg2, _arg3) do
GenServer.start_link(__MODULE__, [])
end
def init(_opts) do
{:ok, "initial state"}
end
end
Use Supervisor.start_link/3 function to start a supervisor with three Worker children using the tuple syntax.
This should cause the supervisor to crash because each Worker has the same id.
Comment your solution when finished to avoid crashing this livebook.
Example Solution ```elixir children = [ {Worker, "initial state"}, {Worker, "initial state"}, {Worker, "initial state"} ] Supervisor.start_link(children, strategy: :one_for_one) ```
Mix Projects
-
Create a new mix empty mix project using the
--supflag. -
Create a new unsupervised mix project without the
--supflag and configure it with a supervisor.
-
Create an Application module in a
lib/my_app/application.exfile. <!– livebook:{“force_markdown”:true} –>
defmodule MyApp.Application do
use Application
def start(_type, _args) do
children = []
Supervisor.start_link(children, strategy: :one_for_one)
end
end
-
Configure the mix project in
mix.exsto use the application module.
def application do
# make sure to keep the existing options and add the following:
[mod: {MyApp.Application, []}]
end
Commit Your Progress
DockYard Academy now recommends you use the latest Release rather than forking or cloning our repository.
Run git status to ensure there are no undesirable changes.
Then run the following in your command line from the curriculum folder to commit your progress.
$ git add .
$ git commit -m "finish Supervisor And GenServer Drills exercise"
$ git push
We’re proud to offer our open-source curriculum free of charge for anyone to learn from at their own pace.
We also offer a paid course where you can learn from an instructor alongside a cohort of your peers. We will accept applications for the June-August 2023 cohort soon.