我应该在哪里调用 Phoenix 中的初始化代码,这可能涉及到数据库的连接?

Where should I call initialization code in Phoenix, which might involve connection to a db?

我有一些代码需要在我的 Elixir Phoneix 应用程序启动时调用。代码的某些部分需要向数据库发出请求以检索将用于初始化的数据。

虽然我可以在

中调用正常代码——不对数据库发出任何请求的代码
defmodule MyAppWeb.Endpoint do 
  # [............]

  #
  # some of my init code will go here
  #


  def init(...) do
    # [.........]
  end
end

如果我理解正确,执行数据库、HTTP 请求或类似操作的代码——可能需要花费大量时间的操作——不应从 MyAppWeb.Endpoint

调用

这是正确的吗?如果是这样,那么我应该从哪里进行初始化的代码?

首先,不要将与 Phoenix 本身无关的代码放入它的助手中。

创建你自己的GenServer,做任何你需要的,然后优雅地停止它。

GenServer初始化过程分为三个阶段:

第一个在调用进程中执行,最后两个是回调,在已经启动的GenServer进程中执行,init/1同步并且handle_continue/2 异步。

也就是说,执行长 运行 初始化的常见做法是:

defmodule MyInit do
  use GenServer

  @spec start_link(opts :: keyword()) :: GenServer.on_start()
  @doc "Starts the GenServer process"
  def start_link(opts \ []) do
    GenServer.start_link(__MODULE__, ..., name: __MODULE__)
  end

  @impl GenServer
  @doc false
  def init(:ok),  do: {:ok, :ok, {:continue, :connect}}

  @impl GenServer
  @doc false
  def handle_continue(:connect, :ok) do
    do_init(...)
    {:stop, :normal, nil}
  end
end

并从你的监督树开始这个过程。


如果在端点启动之前完成此初始化至关重要,请将对do_init的调用移至init/1回调并将此GenServer before 监督树中的端点。