category
4/27/2017 - 8:18 PM

Supervisors in elixir

Supervisors in elixir

Supervisors in Elixir

Configure the worker spec

{:ok, pid} = Supervisor.start_link([Supervisor.Spec.worker(GenServerDB.Worker, [], [])], strategy: :simple_one_for_one)
Key FunctionType SpecNotes
Supervisor.start_link/2start_link([Supervisor.Spec.spec], options) :: on_start[Supervisor.Spec.spec] is usually just a list of workers or supervisors made using Supervisor.Spec.worker/3or Supervisor.Spec.supervisor/3. options need to at least include a strategy: option. To dynamically add workers at runtime, use the :simple_one_for_one strategy.

Dynamically add workers at runtime

iex(3)> {:ok, pid} = Supervisor.start_link([Supervisor.Spec.worker(GenServerDB.Worker, [], [])], strategy: :simple_one_for_one)
iex(4)> Supervisor.start_child(pid, [1])                                                                                                                                                                         
Supervisor.start_child(pid, [1])                                                                                                                                                                                 
{:ok, #PID<0.128.0>}                                                                                                                                                      
iex(6)> Supervisor.start_child(pid, [2])                                                                                                                                                                         
Supervisor.start_child(pid, [2])                                                                                                                                                                                 
{:ok, #PID<0.131.0>}                                                                                                                                                                                               
iex(7)> Supervisor.start_child(pid, [3])                                                                                                                                                                         
Supervisor.start_child(pid, [3])                                                                                                                                                                                 
{:ok, #PID<0.133.0>}
iex(8)> Supervisor.which_children(pid)                                                                                                                                                                             
Supervisor.which_children(pid)                                                                                                                                                                                     
[{:undefined, #PID<0.128.0>, :worker, [GenServerDB.Worker]},                                                                                                                                                       
 {:undefined, #PID<0.131.0>, :worker, [GenServerDB.Worker]},                                                                                                                                                       
 {:undefined, #PID<0.133.0>, :worker, [GenServerDB.Worker]}] 

Create a worker pool

iex(1)> {:ok, pid} = Supervisor.start_link([Supervisor.Spec.worker(GenServerDB.Worker, [], [])], strategy: :simple_one_for_one)                                                                                    
{:ok, pid} = Supervisor.start_link([Supervisor.Spec.worker(GenServerDB.Worker, [], [])], strategy: :simple_one_for_one)                                                                                            
{:ok, #PID<0.120.0>}                                                                                                                                                                                               
iex(2)> for n <- 1..20, do: Supervisor.start_child(pid, [n])                                                                                                                                                       
for n <- 1..20, do: Supervisor.start_child(pid, [n])                                                                                                                                                               
[ok: #PID<0.122.0>, ok: #PID<0.123.0>, ok: #PID<0.124.0>, ok: #PID<0.125.0>,                                                                                                                                       
 ok: #PID<0.126.0>, ok: #PID<0.127.0>, ok: #PID<0.128.0>, ok: #PID<0.129.0>,                                                                                                                                       
 ok: #PID<0.130.0>, ok: #PID<0.131.0>, ok: #PID<0.132.0>, ok: #PID<0.133.0>,                                                                                                                                       
 ok: #PID<0.134.0>, ok: #PID<0.135.0>, ok: #PID<0.136.0>, ok: #PID<0.137.0>,                                                                                                                                       
 ok: #PID<0.138.0>, ok: #PID<0.139.0>, ok: #PID<0.140.0>, ok: #PID<0.141.0>] 
Key FunctionType SpecNotes
Supervisor.start_child/2start_child(supervisor, [term]) :: on_start_child OR start_child(supervisor, Supervisor.Spec.spec) :: on_start_childsupervisor is the supervisor pid, while [term] means a list of additional args to be concatenated to the original worker's start function (GenServer.start_link/3 by default) - use this when using the strategy :simple_one_for_one.

Get a worker PID

iex(2)> for n <- 1..20, do: Supervisor.start_child(pid, [n])                                                                                                                                                       
for n <- 1..20, do: Supervisor.start_child(pid, [n])                                                                                                                                                               
[ok: #PID<0.122.0>, ok: #PID<0.123.0>, ok: #PID<0.124.0>, ok: #PID<0.125.0>,                                                                                                                                       
 ok: #PID<0.126.0>, ok: #PID<0.127.0>, ok: #PID<0.128.0>, ok: #PID<0.129.0>,                                                                                                                                       
 ok: #PID<0.130.0>, ok: #PID<0.131.0>, ok: #PID<0.132.0>, ok: #PID<0.133.0>,                                                                                                                                       
 ok: #PID<0.134.0>, ok: #PID<0.135.0>, ok: #PID<0.136.0>, ok: #PID<0.137.0>,                                                                                                                                       
 ok: #PID<0.138.0>, ok: #PID<0.139.0>, ok: #PID<0.140.0>, ok: #PID<0.141.0>] 
iex(5)> :global.whereis_name({:name, GenServer.DB.Worker, 15})                                                                                                                                                     
:global.whereis_name({:name, GenServer.DB.Worker, 15})                                                                                                                                                             
#PID<0.136.0>                                                                                                                                                                                                      
Key FunctionType SpecNotes
:global.whereis_name/1whereis_name(name) :: pid OR whereis_name(name) :: undefinedThe process name is created inside the worker module - for example as GenServer.start_link(__MODULE__, :ok, [name: {:global, {:name, name}}]. It is then called as the term in {:global, {:name, name}}, i.e. {:name, name}.

Checkout a worker

iex(16)> item = %{'name' => {:name, GenServer.DB.Worker, 7}, 'checkout-window' => %{'from' => Timex.now(), 'to' => Timex.shift(Timex.now, minutes: 10)}}                                                           
item = %{'name' => {:name, GenServer.DB.Worker, 7}, 'checkout-window' => %{'from' => Timex.now(), 'to' => Timex.shift(Timex.now, minutes: 10)}}                                                                    
iex(19)> %{'checkout-windows' => [item]}                                                                                                                                                                           
%{'checkout-windows' => [item]}                                                                                                                                                                                    
%{'checkout-windows' => [%{'checkout-window' => %{'from' => #<DateTime(2017-05-02T06:25:55.198733Z Etc/UTC)>,                                                                                                      
       'to' => #<DateTime(2017-05-02T06:35:55.198832Z Etc/UTC)>},                                                                                                                                                  
     'name' => {:name, GenServer.DB.Worker, 7}}]}