So far we’ve looked at supervision from the point of view of the supervisor. In particular, we’ve seen how the supervision strategy tells the supervisor how to deal with the death of a child process.
There’s a second level of configuration that applies to individual workers. The most commonly used of these is the :restart option.
Previously we said that a supervisor strategy (such as :one_for_all) is invoked when a worker dies. That’s not strictly true. Instead, the strategy is invoked when a worker needs restarting. And the conditions when a worker should be restarted are dictated by its restart: option:
This worker should always be running—it is permanent. This means that the supervision strategy will be applied whenever this worker terminates, for whatever reason.
This worker should never be restarted, so the supervision strategy is never applied if this worker dies.
It is expected that this worker will at some point terminate normally, and this termination should not result in a restart. However, should this worker die abnormally, then it should be restarted by running the supervision strategy.
The simplest way to specify the restart option for a worker is in the worker module. You add it to the use GenServer (or use Supervisor) line:
| defmodule Convolver do |
| use GenServer, restart: :transient |
| # . . . |
You don’t have to know the information in this section first time around, but as someone always asks….
We’ve seen that you start a supervisor by passing it a list of children. Just what is that list?
At the very lowest level, it is a list of child specifications. A child spec is an Elixir map. It describes which function to call to start the worker, how to shut the worker down, the restart strategy, the worker type, and any modules apart from the main module that form part of the worker.
You can create a child spec map using the Supervisor.child_spec/2 function.
At the next level up, you can specify a worker by giving its module name (or a tuple containing the module and the initial arguments). In this case, the supervisor assumes you’ve implemented a child_spec function in that module, and calls that function to get the specification.
Going up one more level, when you add the line use GenServer to a server module, Elixir will define a default child_spec function in that module. This function by default returns a map that tells the supervisor that the start function will be start_link and that the restart strategy will be :permanent. You can override these defaults with the options you give use GenServer.
In practice, the option you’ll change the most will be :restart. Although :permanent is a good default for long-running servers, it won’t work for servers that do a job and then exit. These types of servers should have a restart value of :transient.