Goal
基本的なAgentの使い方を習得する。
Dev-Environment
OS: Windows8.1
Erlang: Eshell V6.4, OTP-Version 17.5
Elixir: v1.0.4
Erlang: Eshell V6.4, OTP-Version 17.5
Elixir: v1.0.4
Wait a minute
プロセスの次は、Agentをやりましょう。
Getting StartのAgentをやった感想としては・・・
ソースコード見ろって感じな内容ですね。
ソースコード見ろって感じな内容ですね。
プロセスの前提知識が必要らしいので、プロセスの基本を習得を読んでおくと理解が早いかもしれません。
Elixirはイミュータブル(作成後にその状態を変えることのできないこと)な言語とのこと。
だから、状態(State)を変えるためには、プロセスかETS(Erlang Term Storage)を利用する必要がある。
(ETSは余り利用される機会はないらしいが)
だから、状態(State)を変えるためには、プロセスかETS(Erlang Term Storage)を利用する必要がある。
(ETSは余り利用される機会はないらしいが)
しかし、プロセスをそのまま使うと色々と面倒である。
だから・・・ElixirとOTPで抽象化されている機能が提供されている。
だから・・・ElixirとOTPで抽象化されている機能が提供されている。
- Agent ・・・ ステート周りのラッパー
- GenServer ・・・ プロセスをカプセル化、同期通信、非同期通信、コードの再読込みをサポート
- GenEvent ・・・ イベントの共有化や複数のハンドラー管理
- Task ・・・ プロセスを発行、後から呼び出しができる(非同期処理)
Index
Agent
|> Preparation
|> KV.Bucket
|> Extra
|> Preparation
|> KV.Bucket
|> Extra
Preparation
Agentを使い、異なるプロセス間で状態を保持します。
その例として、キーバリューストアの読込みや変更を
異なるプロセスで処理を行う簡単なアプリケーションを作成します。
異なるプロセスで処理を行う簡単なアプリケーションを作成します。
プロジェクトを作成します。
>cd プロジェクト作成ディレクトリ
>mix new kv
>cd kv
>mix test
おそらく・・・
kv = key value
kv = key value
KV.Bucket
テストケースとモジュールの二つを作成します。
ファイル: test/bucket_test.exs
defmodule KV.BucketTest do
use ExUnit.Case, async: true
setup do
{:ok, bucket} = KV.Bucket.start_link
{:ok, bucket: bucket}
end
test "stores values by key", %{bucket: bucket} do
assert KV.Bucket.get(bucket, "milk") == nil
KV.Bucket.put(bucket, "milk", 3)
assert KV.Bucket.get(bucket, "milk") == 3
end
test "deletes key from bucket", %{bucket: bucket} do
assert KV.Bucket.delete(bucket, "milk") == nil
KV.Bucket.put(bucket, "milk", 3)
assert KV.Bucket.delete(bucket, "milk") == 3
end
end
Description:
:asyncは、テストが他のテストケースも含めて一斉に実行されるオプション。
:asyncは、テストが他のテストケースも含めて一斉に実行されるオプション。
注意点としては・・・
有効にしている間は、グローバルな値(ファイルシステム、プロセスの登録、データベースの操作など)の参照/変更ができないこと。
上記の操作を行う場合は、テスト間の競合をさけるため非同期させないようにすること。
有効にしている間は、グローバルな値(ファイルシステム、プロセスの登録、データベースの操作など)の参照/変更ができないこと。
上記の操作を行う場合は、テスト間の競合をさけるため非同期させないようにすること。
Description:
テストにおけるコールバック処理の一つ。
テストで毎回必要な同一の処理を記述しておくと便利。
テストにおけるコールバック処理の一つ。
テストで毎回必要な同一の処理を記述しておくと便利。
setup do
{:ok, bucket} = KV.Bucket.start_link
{:ok, bucket: bucket}
end
test "stores values by key", %{bucket: bucket} do
...
end
テストはあまり得意でないので、詳しく書きません。
詳しく知りたい方は、ドキュメントの方を見て下さい。
ドキュメント: hexdocs - v1.0.5 Elixir ExUnit.Case
ドキュメント: hexdocs - v1.0.5 Elixir ExUnit.Callbacks
ドキュメント: hexdocs - v1.0.5 Elixir ExUnit.Assertions
詳しく知りたい方は、ドキュメントの方を見て下さい。
ドキュメント: hexdocs - v1.0.5 Elixir ExUnit.Case
ドキュメント: hexdocs - v1.0.5 Elixir ExUnit.Callbacks
ドキュメント: hexdocs - v1.0.5 Elixir ExUnit.Assertions
ファイル: lib/bucket.ex
defmodule KV.Bucket do
@doc """
Starts a new bucket.
"""
def start_link do
Agent.start_link(fn -> HashDict.new end)
end
@doc """
Gets a value from the `bucket` by `key`.
"""
def get(bucket, key) do
Agent.get(bucket, &HashDict.get(&1, key))
end
@doc """
Puts the `value` for the given `key` in the `bucket`.
"""
def put(bucket, key, value) do
Agent.update(bucket, &HashDict.put(&1, key, value))
end
@doc """
Deletes `key` from `bucket`.
Returns the current value of `key`, if `key` exists.
"""
def delete(bucket, key) do
Agent.get_and_update(bucket, &HashDict.pop(&1, key))
end
end
Description:
・Agent.start_link/2
指定された関数で、現在のプロセスにリンクされているAgentを起動します。
オプションのデフォルト値は空リスト。
オプションのデフォルト値は空リスト。
・Agent.get/3
与えられた関数を介してAgentの値を取得します。
タイムアウトが指定できる。デフォルト値は5000。
タイムアウトが指定できる。デフォルト値は5000。
・Agent.update/3
Agentの状態を更新します。
タイムアウトが指定できる。デフォルト値は5000。
タイムアウトが指定できる。デフォルト値は5000。
・Agent.get_and_update
エージェントの状態を一回の操作で更新/取得します。
タイムアウトが指定できる。デフォルト値は5000。
タイムアウトが指定できる。デフォルト値は5000。
詳しい説明はドキュメントを見て下さい。
ドキュメント: hexdocs - v1.0.5 Elixir Agent
ドキュメント: hexdocs - v1.0.5 Elixir Agent
Extra
質問: 「Agent.start_link(fn -> “” end)」で引数の無名関数は何をやっているのでしょうか?
解答: 初期値の設定。
解答: 初期値の設定。
iex> {:ok, agent} = Agent.start_link(fn -> "" end)
{:ok, #PID<0.61.0>}
iex> Agent.get(agent, fn state -> state end)
""
iex> {:ok, agent} = Agent.start_link(fn -> 2 end)
{:ok, #PID<0.65.0>}
iex> Agent.get(agent, fn state -> state end)
2
@niku氏、ありがとうございました。
Speaking to oneself
クライアントとサーバの区別をしっかりつけましょうって、
注意点が書いてあったが・・・いまいちピンとこないな。
注意点が書いてあったが・・・いまいちピンとこないな。
処理の量や大きさによって負荷の軽減を考えるねぇ。
言われれば、まぁ何となくは想像できるけど・・・
言われれば、まぁ何となくは想像できるけど・・・
まぁやっていく内に分かることでしょう。(楽観)