Vamos testar o comportamento dos 3 tipos de Strategy:
- :one_for_one (Se um processo filho terminar, apenas este processo será reiniciado)
- :one_for_all (Se um processo filho terminar, todos os outros filhos serão terminados e depois, todos os processos seráo reiniciados, inclusive, o processo que terminou)
- :rest_for_one (Se um processo filho terminar, todos os filhos que foram criados depois dele serão finalizados e os mesmos serão reiniciados, inclusive, o processo que terminou)
mix new test_otp --sup
Testando :one_for_one
Vamos configurar no application para os processos sejam criados nessa orderm:
ProcessA
ProcessB
ProcessC
Vamos iniciar cada processo com o estado: [0]
Por padrão, o strategy: já vem como :one_for_one
test_otp/application.ex
defmodule TestOtp.Application do # See https://hexdocs.pm/elixir/Application.html # for more information on OTP Applications @moduledoc false use Application @impl true def start(_type, _args) do children = [ # Starts a worker by calling: TestOtp.Worker.start_link(arg) # {TestOtp.Worker, arg} Core.ProcessA, Core.ProcessB, Core.ProcessC ] # See https://hexdocs.pm/elixir/Supervisor.html # for other strategies and supported options opts = [strategy: :one_for_one, name: TestOtp.Supervisor] Supervisor.start_link(children, opts) end end criar o ProcessA
test_otp/core/process_a.ex
defmodule Core.ProcessA do use GenServer # Server @impl true def init(state) do {:ok, state} end @impl true def handle_call(:get, _from, state) do {:reply, state, state} end @impl true def handle_cast({:add, items}, state) do {:noreply, state ++ items} end # Client def start_link(_) do GenServer.start_link(__MODULE__, [0], name: ProcessA) end def get() do GenServer.call(ProcessA, :get) end def add() do GenServer.cast(ProcessA, {:add, [1,2,3]) end end criar o ProcessB
test_otp/core/process_b.ex
defmodule Core.ProcessB do use GenServer # Server @impl true def init(state) do {:ok, state} end @impl true def handle_call(:get, _from, state) do {:reply, state, state} end @impl true def handle_cast({:add, items}, state) do {:noreply, state ++ items} end # Client def start_link(_) do GenServer.start_link(__MODULE__, [0], name: ProcessB) end def get() do GenServer.call(ProcessB, :get) end def add() do GenServer.cast(ProcessB, {:add, [4,5,6]) end end criar o ProcessC
test_otp/core/process_c.ex
defmodule Core.ProcessC do use GenServer # Server @impl true def init(state) do {:ok, state} end @impl true def handle_call(:get, _from, state) do {:reply, state, state} end @impl true def handle_cast({:add, items}, state) do {:noreply, state ++ items} end # Client def start_link(_) do GenServer.start_link(__MODULE__, [0], name: ProcessC) end def get() do GenServer.call(ProcessC, :get) end def add() do GenServer.cast(ProcessC, {:add, [4,5,6]) end end Vamos iniciar a aplicaçao com o IEX
iex -S mix
Dentro do IEX, vamos digitar
Core.ProcessA.add
Core.ProcessB.add
Core.ProcessC.add
Depois, vamos conferir o estado dos processos:
Core.ProcessA.get
[0,1,2,3]
Core.ProcessB.add
[0,4,5,6]
Core.ProcessC.add
[0,7,8,9]
Agora, vamos parar o ProcessB
Digite no IEX
GenServer.stop(ProcessB)
Agora, vamos conferir o estado dos processos:
Core.ProcessA.get
[0,1,2,3]
Core.ProcessB.add
[0]
Core.ProcessC.add
[0,7,8,9]
Percebemos que apenas o ProcessB voltou ao estado inicial, ou seja, apenas ele foi reiniciado.
Testando :one_for_all
Para isso, vamos mudar apenas o strategy: no arquivo test_otp/application.ex, vamos colocar strategy: :one_for_all
test_otp/application.ex
defmodule TestOtp.Application do # See https://hexdocs.pm/elixir/Application.html # for more information on OTP Applications @moduledoc false use Application @impl true def start(_type, _args) do children = [ # Starts a worker by calling: TestOtp.Worker.start_link(arg) # {TestOtp.Worker, arg} Core.ProcessA, Core.ProcessB, Core.ProcessC ] # See https://hexdocs.pm/elixir/Supervisor.html # for other strategies and supported options opts = [strategy: :one_for_all, name: TestOtp.Supervisor] Supervisor.start_link(children, opts) end end Vamos iniciar a aplicaçao com o IEX
iex -S mix
Dentro do IEX, vamos digitar
Core.ProcessA.add
Core.ProcessB.add
Core.ProcessC.add
Depois, vamos conferir o estado dos processos:
Core.ProcessA.get
[0,1,2,3]
Core.ProcessB.add
[0,4,5,6]
Core.ProcessC.add
[0,7,8,9]
Agora, vamos parar o ProcessB
Digite no IEX
GenServer.stop(ProcessB)
Agora, vamos conferir o estado dos processos:
Core.ProcessA.get
[0]
Core.ProcessB.add
[0]
Core.ProcessC.add
[0]
Percebemos que todos os processos voltaram ao estado inicial, ou seja, todos foram finalizados e reiniciados.
Testando :rest_for_one
Vamos mudar apenas o strategy: no arquivo test_otp/application.ex, vamos colocar strategy: :rest_for_one
test_otp/application.ex
defmodule TestOtp.Application do # See https://hexdocs.pm/elixir/Application.html # for more information on OTP Applications @moduledoc false use Application @impl true def start(_type, _args) do children = [ # Starts a worker by calling: TestOtp.Worker.start_link(arg) # {TestOtp.Worker, arg} Core.ProcessA, Core.ProcessB, Core.ProcessC ] # See https://hexdocs.pm/elixir/Supervisor.html # for other strategies and supported options opts = [strategy: :rest_for_one, name: TestOtp.Supervisor] Supervisor.start_link(children, opts) end end Vamos iniciar a aplicaçao com o IEX
iex -S mix
Dentro do IEX, vamos digitar
Core.ProcessA.add
Core.ProcessB.add
Core.ProcessC.add
Depois, vamos conferir o estado dos processos:
Core.ProcessA.get
[0,1,2,3]
Core.ProcessB.add
[0,4,5,6]
Core.ProcessC.add
[0,7,8,9]
Agora, vamos parar o ProcessB
Digite no IEX
GenServer.stop(ProcessB)
Agora, vamos conferir o estado dos processos:
Core.ProcessA.get
[0,1,2,3]
Core.ProcessB.add
[0]
Core.ProcessC.add
[0]
Percebemos que apenas o ProcessB e o ProcessC) voltaram ao estado inicial. O ProcessB foi parado, por isso, foi reiniciado, já o ProcessC, que foi criado depois do ProcessB, vejam no arquivo application.ex, foi finalizado e reiniciado. E o ProcessA, que foi criado antes do ProcessB, manteve o seu estado, ou seja, não foi reiniciado.






Top comments (2)
Excelente artigo!! Excelente forma de apresentar a ideia, mais simples que isso. Quase impossivel :D
Simples e assertivo na explicação, muito bom!