GenServer
#Elixir #あとで書く
GenServer
Supervisorによって監視が可能
同期・非同期呼び出しを処理可能
GenServer(及びプロセス)はコードの構造化のために使うべきではない(moduleや関数を使って構造化すべき)
チートシート
https://elixir-lang.org/cheatsheets/gen-server.pdf
説明用
code:elixir
defmodule Queue do
use GenServer
def start_link(default) when is_list(default) do
GenServer.start_link(__MODULE__, default)
end
def enqueue(pid, element) do
# 説明のためcastを使っているが、本来この処理にはcallを使うべき
GenServer.cast(pid, {:enqueue, element})
end
def dequeue(pid) do
GenServer.call(pid, :dequeue)
end
@impl true
def init(queue) do
{:ok, queue}
end
@impl true
def handle_call(:dequeue, _from, head | tail) do
{:reply, head, tail}
end
@impl true
def handle_cast({:enqueue, element}, queue) do
{:noreply, queue ++ element}
end
end
{:ok, pid} = Queue.start_link(:hello)
Queue.enqueue(pid, :world) # => :ok
Queue.enqueue(pid, :hoge) # => :ok
Queue.dequeue(pid) # => :hello
Queue.dequeue(pid) # => :world
Queue.dequeue(pid) # => :hoge
メッセージ
call - 同期的
cast - 非同期
info - Kernel.send/2やProcess.monitor等により送信されるメッセージ
API
GenServer.start_link/2
GenServerビヘイビアを実装したモジュールと初期値
GenServer.call/3
callメッセージを送信
GenServer.cast/2
castメッセージを送信
GenServerビヘイビア
init/1
実装が必須
handle_call/3
handle_cast/2
handle_info/2
Kernel.send/2等で送信された通常のメッセージを処理したいときに実装する
supervisorの監視下で動作させる
※use GenServerを実行すると、自動的にchild_spec/1が定義される
code:elixir
children = [{Queue, :hoge}]
Supervisor.start_link(children, strategy: :one_for_all)
参考
https://hexdocs.pm/elixir/GenServer.html
https://elixir-lang.org/getting-started/mix-otp/genserver.html