编写一些小实验以使自己熟悉该语言,但是遇到了一个我认为很基本​​的问题。

我有一个简单的主管,有3个简单的工人:

def init do
    Supervisor.start_link(
       [
          worker(__MODULE__, [:"process-1"], [function: :test, id: :"p-1"]),
          worker(__MODULE__, [:"process-2"], [function: :test, id: :"p-2"]),
          worker(__MODULE__, [:"process-3"], [function: :test, id: :"p-3"])
       ],
       strategy: :one_for_one
    )
end

“:test”看起来像这样:
def test(name) do
    flag(:trap_exit, true)

    IO.puts "Testing: #{name} == #{inspect self}"

    register(self, name)

    receive do
        { :death } ->
            IO.puts("I WOZ MURDERED!")
            exit(self, "Ex process...")
        { :life } ->
            IO.puts("#{inspect self} is listening...")
            __MODULE__.test(name)
        { :EXIT, pid, reason } ->
            IO.puts "REASON: #{inspect reason} - PROCESS: #{inspect pid}"
    end
end

这样可以编译,但是只能生成一个进程,并挂起/阻止iex。

相反,当我使用一条简单的“spawn_link”处理链时,所有三个(或许多)进程同时启动,并将控制权返回给iex shell,因此我可以从命令行发送已注册的进程消息。

目前,我的意图是创建一个OTP主管,运行并注册三个(或多个)工作者进程,并将它们附加到主管,发送一条简单的消息杀死给定的工人,然后让主管重新启动它。

我究竟做错了什么?

最佳答案

问题是您作为工作程序规范的一部分提供的function:不能达到OTP的预期。

http://www.erlang.org/doc/man/supervisor.html

启动函数必须创建并链接到子进程,并且
应该返回{ok,Child}或{ok,Child,Info},其中Child是
子进程和Info是一个任意术语,该术语将被忽略
主管

您的代码不会产生孩子,但会进入接收循环。您也许可以使用Elixir的Task模块执行与您想要的外观类似的操作:

worker(Task, [__MODULE__, :test, [:"process-1"]], id: :"p-1"),
worker(Task, [__MODULE__, :test, [:"process-2"]], id: :"p-2"),
worker(Task, [__MODULE__, :test, [:"process-3"]], id: :"p-3")

但是,如果您想了解有关OTP功能的更多信息,那么尝试实现自己的GenServer可能是一个更好的选择。

09-12 09:56