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!