我应该在凤凰城哪里调用初始化代码,这可能涉及到数据库的连接?
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
和那里的链接。以上是关于我应该在凤凰城哪里调用初始化代码,这可能涉及到数据库的连接?的主要内容,如果未能解决你的问题,请参考以下文章
如果涉及访问外部API(域驱动设计),我应该在哪里放置值对象创建逻辑]] << [