スポンサーリンク

2016年2月10日

[Elixir]Supervisorでの疑問について調査

とある錬金術師の万能薬(Elixir)

Goal

Supervisorのworker/3とsupervisor/3の使い分けについて理解する。
また、start_link/2とsupervise/2の使い分けについても少々。

Dev-Environment

OS: Windows8.1
Erlang: Eshell V7.2.1, OTP18
Elixir: v1.2.0

Context

ふと疑問に思ったんです。
Supervisorを使うときに、workerで登録しているものとsupervisorで登録している違いって何?っと…
基本的なことなんでしょうけど、実は意識してなかったので知らなかったのです。
そういうわけで、本日は時間も取れないので疑問の解消をちゃちゃっとしてしまいます。

Example:

children = [
  supervisor(ExampleApp.MySupervisor, [[name: ExampleApp.MySupervisor]]),
  worker(ExampleModule, [[], [name: ExampleModule]])
]
例の通りなのですが…
まずsupervisor/3ですが、これはスーパーバイザ(監視者)の定義を行っているものになります。
worker/3は、GenServerやGenEventなどで実装したモジュール(労働者)を定義しています。
まぁとりあえず、スーパーバイザを定義するならsupervisor/3使って、
それ以外はworker/3使ってれば大丈夫でしょう。
次、start_link/2を使う場合とsupervise/2使う場合の違いについて…

Example:

これと
{:ok, pid} = Supervisor.start_link(children, strategy: :one_for_one)
これの
supervise(children, strategy: :one_for_one)
使い分けは?
とりあえず、Elixirのソースコードを見に行く…

Quote:

  • start_link/2
@spec start_link([Supervisor.Spec.spec], options) :: on_start
def start_link(children, options) when is_list(children) do
  spec = Supervisor.Spec.supervise(children, options)
  start_link(Supervisor.Default, spec, options)
end
start_link/2の中でsupervise/2呼んでるやん…
  • supervise/2
@spec supervise([spec], strategy: strategy,
                        max_restarts: non_neg_integer,
                        max_seconds: non_neg_integer) :: {:ok, tuple}
def supervise(children, options) do
  unless strategy = options[:strategy] do
    raise ArgumentError, "expected :strategy option to be given"
  end

  maxR = Keyword.get(options, :max_restarts, 3)
  maxS = Keyword.get(options, :max_seconds, 5)

  assert_unique_ids(Enum.map(children, &elem(&1, 0)))
  {:ok, {{strategy, maxR, maxS}, children}}
end
さて…よう分からなくなってきたぞ。
公式のSupervisorのドキュメントには以下のように書いてある。

Quote:

Module-based supervisors
In the example above, a supervisor was dynamically created by passing the supervision structure to start_link/2.
However, supervisors can also be created by explicitly defining a supervision module:
Google翻訳するとこんな感じになる。
上記の例では、スーパーバイザは動的をstart_link/2する監督構造を渡すことによって作成されました。
しかし、上司はまた明示的に監視モジュールを定義することによって作成することができます。
答え書いてありますね。
しかし、上司はまた明示的に監視モジュールを定義することによって作成することができます。
明示的に監視モジュールを定義する場合は、supervise/2を使えばいいと…

Quote:

  • start_link/2
import Supervisor.Spec

children = [
  worker(ExampleModule, [[:hello], [name: :example]])
]

# Start the supervisor with our one child
{:ok, pid} = Supervisor.start_link(children, strategy: :one_for_one)
  • supervise/2
defmodule MyApp.Supervisor do
  use Supervisor

  def start_link do
    Supervisor.start_link(__MODULE__, [])
  end

  def init([]) do
    children = [
      worker(ExampleModule, [[:hello]])
    ]

    supervise(children, strategy: :one_for_one)
  end
end
childrenに定義した監視対象を登録するときにsupervise/2をして、
監視を開始するときにstart_link/2を使えばいいってことかな…
何にせよ、今日はここまで…
間違っていればいずれ気づくでしょう…(致命的なミスにならないことを祈る)
Supervisor面白いな早く自在使えるようになりたい…こんなこともできるってことですよね。
親Supervisor
|-モジュール
|-Supervisor
| |-モジュール
| |-Supervisor
|-Supervisor
少しは成長できた…と思いたい(願望)
ノシ

Bibliography

人気の投稿