为什么这个 child 进程在我启动它的 parent 时没有启动?

Why doesn't this child process get started when I start its parent?

假设我有以下主管树设置,其中一个 parent 开始 child 并且 child 开始它的 grandchild:

defmodule NestedSupervisorTree do
  # this will be the top line supervisor
  use Supervisor

  def start_link, do: Supervisor.start_link(__MODULE__, :ok, name: __MODULE__)

  def init(:ok) do
    children = [
      supervisor(BranchSupervisor, [], restart: :temporary)
      #worker(TreeWorker, [], restart: :temporary)
    ]

    supervise(children, strategy: :simple_one_for_one)

  end

  def start_branch(args) do
    {_, branch_id} = Supervisor.start_child(__MODULE__, [args])
  end
end

defmodule BranchSupervisor do
  # this will be the top line supervisor
  use Supervisor

  def start_link(args), do: Supervisor.start_link(__MODULE__, [args], name: __MODULE__)

  def init(args) do
    IO.puts "branch init args:"
    IO.inspect args
    children = [
      worker(TreeWorker, [args], restart: :temporary)
    ]

    supervise(children, strategy: :simple_one_for_one)
  end

  def start_worker do
    {_, wid} = Supervisor.start_child(__MODULE__, [])
  end
end

defmodule TreeWorker do
  def start_link(args) do
    IO.puts "worker args:"
    IO.inspect args
    #IO.puts String.codepoints raw
    {:ok, spawn(fn -> loop end)}
  end

  def loop do
    receive do
      :stop -> :ok

      msg ->
        IO.inspect msg
        loop
    end
  end
end

假设我在 iex 终端中按以下顺序发出以下命令:

 iex> {_, pid} = NestedSupervisorTree.start_link
 iex> {_, cid} = NestedSupervisorTree.start_branch(2)

为什么 BranchSupervisor 的 grandchild 没有启动?当我执行 Supervisor.which_children(cid) 时,我得到一个空列表...我认为 BranchSupervisor#init 在调用 NestedSupervisorTree.start_branch( 2) 后跟 NestedSupervisorTree#start_link。我还认为 BranchSupervisor#init 末尾的监督启动了 children...?或者它只是告诉你哪个 "type of children" BranchSupervisor 可以监督和 "strategy" 监督他们?

当您将 strategy 设置为 :simple_one_for_one 时,Supervisor 不会自动启动任何 child。它接受 children 列表中的一项作为稍后调用 start_child 时的模板。如果您想启动 child 进程,您需要自己调用 start_child。如果您只想启动一个 child 并且希望它自动完成,您可能正在寻找 :one_for_one 策略。

来自Supervisor documentation

:simple_one_for_one - similar to :one_for_one but suits better when dynamically attaching children. This strategy requires the supervisor specification to contain only one child. Many functions in this module behave slightly differently when this strategy is used.

the simple one for one specification can define only one child which works as a template for when we call start_child/2