Elixir 태스크 모듈의 힘 - Into Task.Supervisor
이제
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
및 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
는 실행 전후에 동일합니다.
프로세스와 감독자 트리는 탄력성과 내결함성 시스템을 구축하기 위한 엘릭서의 중요한 구성 요소입니다.
Reference
이 문제에 관하여(Elixir 태스크 모듈의 힘 - Into Task.Supervisor), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/felipearaujos/the-power-of-elixir-task-module-into-task-supervisor-5365
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
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
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
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>
이제 감독된 작업을 사용하는 단계에 있습니다. 열어봅시다
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
는 실행 전후에 동일합니다.프로세스와 감독자 트리는 탄력성과 내결함성 시스템을 구축하기 위한 엘릭서의 중요한 구성 요소입니다.
Reference
이 문제에 관하여(Elixir 태스크 모듈의 힘 - Into Task.Supervisor), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/felipearaujos/the-power-of-elixir-task-module-into-task-supervisor-5365텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)