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

Posted

技术标签:

【中文标题】我应该在凤凰城哪里调用初始化代码,这可能涉及到数据库的连接?【英文标题】:Where should I call initialization code in Phoenix, which might involve connection to a db? 【发布时间】:2020-03-24 20:23:40 【问题描述】:

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

虽然我可以在

中调用普通代码——不对数据库做任何请求的代码
defmodule MyAppWeb.Endpoint do 
  # [............]

  #
  # some of my init code will go here
  #


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

如果我理解正确,不应该从MyAppWeb.Endpoint调用执行数据库、HTTP 请求或类似的代码(可能需要很长时间)

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

【问题讨论】:

您应该从这里查看ReleaseTasks:hexdocs.pm/mix/Mix.Tasks.Release.html @Daniel 我真的怀疑我是否遵循发布任务在这里会有什么帮助。 是的,我的错,我想指出配置提供者:hexdocs.pm/mix/Mix.Tasks.Release.html#module-config-providers @Daniel 配置提供程序都是关于要加载的静态配置,从那里执行一些代码绝对是一种反模式。 【参考方案1】:

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

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

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

GenServer.start_link/3 GenServer.init/1 GenServer.handle_continue/2

第一个在调用进程中执行,最后两个是回调,在已经启动的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 之前监督树中的端点。

【讨论】:

GenServer应该叫supervisor(MyInit)还是worker(MyInit)?还是没关系? 另外,通过我的MyInit,我需要调用我的应用程序中的另一个 GenServer,特别是ets。有什么细微差别吗? supervisor(MyInit) / worker(MyInit) 在很久以前就被弃用了。 GenServer 暴露了child_spec,所以只需将其放入监督树中ets 绝不是GenServer,不,没有细微差别,只需打开它并调用(注意ets 归调用进程所有,所以如果你从这个GenServer 打开它,让它继续运行。 into the supervision tree 是什么意思?你能告诉我代码吗?在application.ex 我有def start(_type, _args) do,其中有多个supervisors(AAA)worker(MyInit) 是的,在那里。有大量关于该主题的文档。 Application 和那里的链接。

以上是关于我应该在凤凰城哪里调用初始化代码,这可能涉及到数据库的连接?的主要内容,如果未能解决你的问题,请参考以下文章

数据应该在哪里加载到 ViewModel

iOS - 在哪里初始化视图

如果涉及访问外部API(域驱动设计),我应该在哪里放置值对象创建逻辑]] << [

如果不在 viewDidLoad 中,我应该在哪里进行初始网络调用(例如,最初填充提要)?

我应该在 Laravel MVC 中的哪里保存模型?

之前:获取最后插入的 id - mysql 现在:我们应该在哪里调用最后插入的 id?