@@ -20,8 +20,8 @@ defmodule Supervisor do
20
20
defmodule Stack do
21
21
use GenServer
22
22
23
- def start_link(state) do
24
- GenServer.start_link(__MODULE__, state, [name: :sup_stack] )
23
+ def start_link(state, opts ) do
24
+ GenServer.start_link(__MODULE__, state, opts )
25
25
end
26
26
27
27
def handle_call(:pop, _from, [h|t]) do
@@ -38,16 +38,17 @@ defmodule Supervisor do
38
38
# Import helpers for defining supervisors
39
39
import Supervisor.Spec
40
40
41
- # We are going to supervise the Stack server which will
42
- # be started with a single argument [:hello]
41
+ # We are going to supervise the Stack server which
42
+ # will be started with a single argument [:hello]
43
+ # and the default name of :sup_stack.
43
44
children = [
44
- worker(Stack, [[:hello]])
45
+ worker(Stack, [[:hello], [name: :sup_stack] ])
45
46
]
46
47
47
48
# Start the supervisor with our one child
48
49
{:ok, pid} = Supervisor.start_link(children, strategy: :one_for_one)
49
50
50
- Notice that when starting the GenServer, we have registered it
51
+ Notice that when starting the GenServer, we are registering it
51
52
with name `:sup_stack`, which allows us to call it directly and
52
53
get what is on the stack:
53
54
@@ -65,7 +66,7 @@ defmodule Supervisor do
65
66
Let's try it:
66
67
67
68
GenServer.call(:sup_stack, :pop)
68
- =ERROR REPORT====
69
+ ** (exit) exited in: GenServer.call(:sup_stack, :pop, 5000)
69
70
70
71
Luckily, since the server is being supervised by a supervisor, the
71
72
supervisor will automatically start a new one, with the default stack
@@ -136,6 +137,49 @@ defmodule Supervisor do
136
137
in this module behave slightly differently when this strategy is
137
138
used.
138
139
140
+ ## Simple one for one
141
+
142
+ The simple one for one supervisor is useful when you want to dynamically
143
+ start and stop supervisor children. For example, imagine you want to
144
+ dynamically create multiple stacks. We can do so by defining a simple one
145
+ for one supervisor:
146
+
147
+ # Import helpers for defining supervisors
148
+ import Supervisor.Spec
149
+
150
+ # This time, we don't pass any argument because
151
+ # the argument will be given when we start the child
152
+ children = [
153
+ worker(Stack, [], restart: :transient)
154
+ ]
155
+
156
+ # Start the supervisor with our one child
157
+ {:ok, sup_pid} = Supervisor.start_link(children, strategy: :simple_one_for_one)
158
+
159
+ There are a couple differences here:
160
+
161
+ * The simple one for one specification can define only one child which
162
+ works as a template for when we call `start_child/2`
163
+
164
+ * We have define the child to have restart strategy of transient. This
165
+ means that, if the child process exits due to a `:normal`, `:shutdown`
166
+ or `{:shutdown, term}` reason, it won't be restarted. This is useful
167
+ as it allows our workers to politely shutdown and be removed from the
168
+ simple one for one supervisor, without being restarted
169
+
170
+ With the supervisor defined, let's dynamically start stacks:
171
+
172
+ {:ok, pid} = Supervisor.start_child(sup_pid, [[:hello, :world], []])
173
+ GenServer.call(pid, :pop) #=> :hello
174
+ GenServer.call(pid, :pop) #=> :world
175
+
176
+ {:ok, pid} = Supervisor.start_child(sup_pid, [[:something, :else], []])
177
+ GenServer.call(pid, :pop) #=> :something
178
+ GenServer.call(pid, :pop) #=> :else
179
+
180
+ Supervisor.count_children(sup_pid)
181
+ #=> %{active: 2, specs: 1, supervisors: 0, workers: 2}
182
+
139
183
## Name Registration
140
184
141
185
A supervisor is bound to the same name registration rules as a `GenServer`.
0 commit comments