Testando os tipos de Strategy do Supervisor do Elixir
Vinicius Moreira
Posted on June 24, 2022
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.
Posted on June 24, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.