【问题标题】:Elixir supervisor -init- dynamically start childrenElixir supervisor -init - 动态启动子进程
【发布时间】:2016-09-01 16:46:03
【问题描述】:

我有一个简单的主管模块,例如:

defmodule Final.Users.Supervisor do
  use Supervisor

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

  def init(:ok) do    
    children = [
      worker(Final.UserServer, [], restart: :temporary)
    ]

    supervise(children, strategy: :simple_one_for_one)
  end

  def create_user(id), do: Supervisor.start_child(__MODULE__, [id])

end

在应用程序启动时我想做的是查找数据库并为 db 中的每个用户条目调用 create_user/1。

我在 init 中尝试了 Process.send_after()... 但它给出了错误(** (EXIT) 进程试图调用自身)

在这个模块中尝试这样做是否有意义?我是否应该设置另一个工作人员(genserver),然后查询数据库并调用此 Users.Supervisor.create_user/1 ?示例:

defmodule Final.Users.Starter do
  alias Final.Repo
  alias Final.Users.Supervisor, as: Sup
  import Ecto.Query, only: [from: 2]
  use GenServer

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

  def init(:ok) do
    Process.send_after(self(), :started, 0)
    {:ok, %{}}
  end

  def handle_info(:started, %{}) do
    query = from(p in "users",
            select: p.id)
    ids = Final.Repo.all(query)
    Enum.each(ids, fn(x) -> Sup.create_user(x) end)

    {:noreply, %{}}
  end
end

【问题讨论】:

  • “我在 init 中尝试了 Process.send_after()... 但它给出了错误(** (EXIT) 进程试图调用自身)”Process.send_after/3 in init/1 对我来说很好GenServer(我复制了你的 Final.Users.Starter 并删除了 Ecto 和 Supervisor 相关的东西)。你能发布你得到的那个错误的堆栈跟踪吗?该错误仅在进程尝试向自身发送GenServer.call 时引发(这将导致死锁)。

标签: elixir


【解决方案1】:

您不能在主管的init/1 回调中启动动态子进程,因为此函数会将子进程规范返回给新启动的主管进程。换句话说,在这个回调返回之前,主管不知道如何启动子进程。

仅仅为了做一些初始化工作而设置 GenServer 似乎太多了。一个更好的主意是生成一个临时进程来完成这项工作并立即退出。

为此,您可以使用Task

Task.start_link(fn -> 
                  query = from(p in "users", select: p.id)
                  ids = Final.Repo.all(query)
                  Enum.each(ids, fn(x) -> Sup.create_user(x) end)
                end)

此类任务可以从您应用程序的主模块中生成。但请注意,如果此任务失败,将向调用者发送退出信号。

【讨论】:

  • 您可以将调用&start_link/1 替换为调用&start/1。这样,任务就可以失败,而不会破坏监督树的某些部分
猜你喜欢
  • 2019-05-14
  • 1970-01-01
  • 2016-11-28
  • 2012-10-12
  • 2012-02-11
  • 2013-01-06
  • 2020-02-21
  • 1970-01-01
  • 2015-12-08
相关资源
最近更新 更多