В Elixir, используя супервизор simple_one_for_one и start_child, как я могу установить идентификатор дочернего элемента в супервизоре?

#elixir #erlang-otp

#elixir #erlang-otp

Вопрос:

Вот простой супервизор тестирования:

 defmodule SupervisorTest.Worker.Supervisor do
  use Supervisor

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

  def start_worker(args) do
    Supervisor.start_child(__MODULE__, [args])
  end

  def init(:ok) do
    children = [
      worker(SupervisorTest.Worker, [])
    ]

    supervise(children, strategy: :simple_one_for_one)
  end
end
  

И вот мой еще более простой рабочий:

 defmodule SupervisorTest.Worker do
  use GenServer

  def start_link(args) do
    GenServer.start_link(__MODULE__, args)
  end

  def state(pid) do
    GenServer.call(pid, :state)
  end

  def stop(pid) do
    GenServer.stop(pid, :normal)
  end

  def handle_call(:state, _from, state) do
    {:reply, state, state}
  end
end
  

В идеале я хотел бы иметь возможность звонить Supervisor.which_children с этим супервизором и получать список дочерних кортежей, причем идентификатор является сгенерированным UUID. Похоже, я не могу установить это в init worker инструкции. И нет никаких start_child/3 вариантов, которые принимают. И я не могу вызвать start_child/2 вывод другого worker оператора… Итак, я не вижу способа установить идентификатор на что-либо… Есть идеи?

Этот код, написанный, когда я вызываю Supervisor.which_children , первым элементом каждого дочернего кортежа является :undefined .

Ответ №1:

Согласно документации Supervisor.which_children/1 и superviser:which_children/1 , это невозможно для :simple_one_for_one супервизоров:

id — как определено в дочерней спецификации или :undefined в случае simple_one_for_one супервизора

Id — Как определено в спецификации дочернего элемента или undefined для simple_one_for_one супервизора.

Итак, для simple_one_for_one супервизоров первым элементом возвращаемых кортежей всегда будет :undefined .

Ответ №2:

вы можете сгенерировать UUID в

 def start_worker(args) do
  uuid = <generate UUID>,
  Supervisor.start_child(__MODULE__, [args, uuid])
end
  

на стороне рабочего:

 def start_link(args, uuid) do
  GenServer.start_link(__MODULE__, [args, uuid])
end

def init([args,uuid]) do
  {:ok, #State{ uuid: uuid }}
end
  

таким образом, когда вы получаете which_children, вы можете запросить UUID дочерних элементов через их pid.