Elixirタスクモジュールのパワー-タスクに.主任


タスクモジュールについてのイントロで、より一般的な方法で動作します.
今では物事を少し複雑にする時間ですTask.Supervisor といくつかのエリクサーの概念を参照してください.
先に進む前に、いくつかのエリクサーベースの概念を見てみましょう.
Supervisor

A supervisor is a process that supervises other processes, which we refer to as child processes. Supervisors are used to building a hierarchical process structure called a supervision tree. Supervision trees provide fault-tolerance and encapsulate how our applications start and shutdown.


Processes

In Elixir, all code runs inside processes. Processes are isolated from each other, run concurrent to one another, and communicate via message passing.

Elixir’s processes should not be confused with operating system processes. Processes in Elixir are extremely lightweight in terms of memory and CPU (even compared to threads as used in many other programming languages). Because of this, it is not uncommon to have tens or even hundreds of thousands of processes running simultaneously.


私たちはTask.Supervisor 関連する子を管理するプロセスを作成する.

遊び場の作成
最初のステップは、監督の木と新しいエリクサーアプリケーションを作成し、ミックスの可能性についての詳細情報を見つけることができますin the official documentation .
mix new newsample --sup
作成されたものを見る時間
  lib
  lib/newsample
  lib/newsample.ex
  lib/newsample/application.ex
test
  test/newsample_test.exs
  test/test_helper.exs
README.md
mix.exs
今のところ私たちはlib/newsample.ex and lib/newsample/application.ex .
番目のステップは、前の投稿から同じ機能を作成することですlib/newsample.ex マイナーな変更を簡単に我々のテストを実行します.
爆発的なシナリオを強制するために、我々は「アルファ」値と一致しているパターンを持っています.
  def say_hello("alpha" = to), do: raise("Error to say hello to #{to}")

  def say_hello(to) do
    IO.puts("Hello #{to}")
    :ok
  end

  def process() do
    items = ["alpha", "beta", "gama"]

    Enum.map(items, fn item ->
      Task.async(fn ->
        say_hello(item)
      end)
    end)
    |> Enum.map(&Task.await/1)
  end
そして最後にelixir's interactive shell .
iex -S mix
次に、コードを実行します.
iex(1)> self
#PID<0.145.0>
iex(2)> Newsample.process
Hello beta
Hello gama

22:01:54.276 [error] Task #PID<0.148.0> started from #PID<0.145.0> terminating
** (RuntimeError) Error to say hello to alpha
    (newsample 0.1.0) lib/newsample.ex:15: anonymous fn/2 in Newsample.process/1
    (elixir 1.11.3) lib/task/supervised.ex:90: Task.Supervised.invoke_mfa/2
    (elixir 1.11.3) lib/task/supervised.ex:35: Task.Supervised.reply/5
    (stdlib 3.14) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Function: #Function<1.13017213/0 in Newsample.process/1>
    Args: []
** (EXIT from #PID<0.145.0>) shell process exited with reason: an exception was raised:
    ** (RuntimeError) Error to say hello to alpha
        (newsample 0.1.0) lib/newsample.ex:15: anonymous fn/2 in Newsample.process/1
        (elixir 1.11.3) lib/task/supervised.ex:90: Task.Supervised.invoke_mfa/2
        (elixir 1.11.3) lib/task/supervised.ex:35: Task.Supervised.reply/5
        (stdlib 3.14) proc_lib.erl:226: :proc_lib.init_p_do_apply/3

Interactive Elixir (1.11.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> self
#PID<0.151.0>
我々が見ることができるように、上がる例外はiex セッション.それを比較するのをチェックすることは可能ですPID 以前#PID<0.145.0> 以降#PID<0.151.0> コードを実行します.

どのように、我々はこの爆発的エラー伝播を避けますか?
今、我々は監督のタスクを使用するには、オープンしましょうlib/newsample/application.ex .
  def start(_type, _args) do
    children = []

    opts = [strategy: :one_for_one, name: Newsample.Supervisor]
    Supervisor.start_link(children, opts)
  end
をつくりましょうTask.Supervisor 子プロセスとして
  children = [
    {Task.Supervisor, name: Newsample.TaskSupervisor}
  ]
そして今、この監督のタスクを使用してprocess 方法と開始async_no_link . この子プロセスと親プロセスの間にリンクがないことを意味します.
  def process() do
    items = ["alpha", "beta", "gama"]

    Enum.map(items, fn item ->
      Task.Supervisor.async_nolink(Newsample.TaskSupervisor, fn ->
        say_hello(item)
      end)
    end)
    |> Enum.map(&Task.await/1)
  end
我々が再び実行するならば、すべてはこの誤り伝播なしで正しく働きます.
iex(1)> self
#PID<0.158.0>
iex(2)> Newsample.process
Hello beta
Hello gama

21:04:48.200 [error] Task #PID<0.161.0> started from #PID<0.158.0> terminating
** (RuntimeError) Error to say hello to alpha
    (newsample 0.1.0) lib/newsample.ex:6: Newsample.say_hello/1
    (elixir 1.11.3) lib/task/supervised.ex:90: Task.Supervised.invoke_mfa/2
    (elixir 1.11.3) lib/task/supervised.ex:35: Task.Supervised.reply/5
    (stdlib 3.14) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Function: #Function<1.39266525/0 in Newsample.process/0>
    Args: []
** (exit) exited in: Task.await(%Task{owner: #PID<0.158.0>, pid: #PID<0.161.0>, ref: #Reference<0.1303494724.713818114.156158>}, 5000)
    ** (EXIT) an exception was raised:
        ** (RuntimeError) Error to say hello to alpha
            (newsample 0.1.0) lib/newsample.ex:6: Newsample.say_hello/1
            (elixir 1.11.3) lib/task/supervised.ex:90: Task.Supervised.invoke_mfa/2
            (elixir 1.11.3) lib/task/supervised.ex:35: Task.Supervised.reply/5
            (stdlib 3.14) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
    (elixir 1.11.3) lib/task.ex:639: Task.await/2
    (elixir 1.11.3) lib/enum.ex:1411: Enum."-map/2-lists^map/1-0-"/2
iex(2)> self
#PID<0.158.0>
我々が見ることができるようにPID は実行の前後で同じです.
プロセスとスーパーバイザ木は、回復と耐故障システムを構築するために、エリクサーの重要な構成要素です.