2016年12月6日火曜日

Elixirで「GenServer」(その2)

Elixirで「GenServer」(その2)です。Cultttさんの「Understanding GenServer in Elixir」のブログを読んで、ようやく、どういうことか見えてきたような気がします。

/lib/kv/shopping_list.ex
defmodule ShoppingList do
  use GenServer
 
  # Client API
 
  def start_link do
    # 1. サーバーのコールバックが実装される場所(同じモジュール内に実装する場合は「__MODULE__」)
    # 2. モジュールの初期化引数(何もなければ「:ok」)
    # 3. オプションのリスト([])
    GenServer.start_link(__MODULE__, :ok, [])
  end
 
  def read(pid) do
    # callは、サーバーからの応答を受信するまでプロセスをブロック。
    # 1. プロセスのPID
    # 2. リクエスト
    GenServer.call(pid, {:read})
  end

  def add(pid, item) do
    # castは、サーバーからの応答を待たない。
    # 1. プロセスのPID
    # 2. リクエスト
    GenServer.cast(pid, {:add, item})
  end
 
  # Server Callbacks
 
  # サーバーを初期化
  def init(:ok) do
    {:ok, []}
  end
 
  # 1. リクエスト
  # 2. プロセスのPID
  # 3. 現在の状態
  def handle_call({:read}, from, list) do
    {:reply, list, list}
  end
 
  # 1. リクエスト
  # 2. 現在の状態
  def handle_cast({:add, item}, list) do
    {:noreply, list ++ [item]}
  end
end
実際に利用してみた例
$ iex -S mix

iex(1)> {:ok, pid} = ShoppingList.start_link
{:ok, #PID<0.123.0>}

iex(2)> ShoppingList.add(pid, "milk")
:ok

iex(3)> ShoppingList.add(pid, "bread")
:ok

iex(4)> ShoppingList.add(pid, "cheese")
:ok

iex(5)> ShoppingList.read(pid)
["milk", "bread", "cheese"]

参考サイト
Understanding GenServer in Elixir(Culttt)
Elixirでクライアント・サーバ関係を実装する「GenServer」

0 件のコメント:

コメントを投稿