Skip to content

Instantly share code, notes, and snippets.

@allenyang79
Last active May 16, 2020 17:18
Show Gist options
  • Save allenyang79/3a425c4895949e944203b8889e498a47 to your computer and use it in GitHub Desktop.
Save allenyang79/3a425c4895949e944203b8889e498a47 to your computer and use it in GitHub Desktop.
  • 比較Supervisor 和DynamicSupervisor的差異性
  • 了解child_spec裡的內容
defmodule SimpleQueue do
use GenServer
require Logger
def child_spec(init_args \\ []) do
Logger.info("child_spec, #{inspect(init_args)}")
%{
id: SimpleQueue,
start: {__MODULE__, :start_link, [init_args]},
shutdown: 5_000,
restart: :permanent,
type: :worker
}
end
### Client API / Helper functions
def start_link(init_args) do
Logger.info("start_link, #{inspect(init_args)}")
GenServer.start_link(__MODULE__, init_args)
end
def queue(pid), do: GenServer.call(pid, :queue)
def enqueue(pid, value), do: GenServer.cast(pid, {:enqueue, value})
def dequeue(pid), do: GenServer.call(pid, :dequeue)
### GenServer callbacks
@doc """
GenServer.init/1 callback
"""
def init(init_args) do
Logger.info("init, #{inspect(init_args)}")
{:ok, init_args}
end
@doc """
GenServer.handle_call/3 callback
"""
def handle_call(:dequeue, _from, [value | state]) do
{:reply, value, state}
end
def handle_call(:dequeue, _from, []), do: {:reply, nil, []}
def handle_call(:queue, _from, state), do: {:reply, state, state}
@doc """
GenServer.handle_cast/2 callback
"""
def handle_cast({:enqueue, value}, state) do
{:noreply, state ++ [value]}
end
end
defmodule SimpleQueue.Supervisor do
@moduledoc """
usage:
{:ok, sup_pid} = SimpleQueue.Supervisor.start_link()
{:ok, pid_1} = SimpleQueue.Supervisor.create()
{:ok, pid_2} = SimpleQueue.Supervisor.create(:alias_pid_2)
Supervisor.which_children(sup_pid)
"""
use Supervisor
require Logger
@sup_pid __MODULE__
#######
# API #
#######
def start_link() do
Supervisor.start_link(__MODULE__, :ok, name: @sup_pid)
end
@doc """
start_child(
supervisor(),
:supervisor.child_spec() | {module(), term()} | module()
) :: on_start_child()
"""
def create(id \\ SimpleQueue) do
Logger.info("create")
child_spec = Supervisor.child_spec(SimpleQueue, [id: id])
Logger.info("child_spec, #{inspect(child_spec)}")
Supervisor.start_child(@sup_pid, child_spec)
end
#############
# callbacks #
#############
def init(:ok) do
Supervisor.init([], strategy: :one_for_one)
end
end
defmodule SimpleQueue.DynamicSupervisor do
use DynamicSupervisor
require Logger
@moduledoc """
{:ok, sup_pid} = SimpleQueue.DynamicSupervisor.start_link()
{:ok, pid_1} = SimpleQueue.DynamicSupervisor.create()
"""
@sup_pid __MODULE__
@spec start_link :: :ignore | {:error, any} | {:ok, pid}
def start_link() do
DynamicSupervisor.start_link(__MODULE__, :ok, name: @sup_pid)
end
@doc """
Start a Player process and add it to supervision
"""
def create() do
Logger.info("create")
child_spec = %{
id: SimpleQueue,
start: {SimpleQueue, :start_link, [[1,2,3]]},
shutdown: 5_000,
restart: :permanent,
type: :worker
}
Logger.info("child_spec, #{inspect(child_spec)}")
DynamicSupervisor.start_child(@sup_pid, child_spec)
end
############
# callback #
############
@doc """
DynamicSupervisor only support one_for_one
"""
def init(:ok) do
DynamicSupervisor.init(
strategy: :one_for_one,
max_children: 3,
)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment