调用Phoenix应用程序启动时从数据库加载一些数据的函数的最简单方法是什么?因此,我需要我的函数具有Ecto.Query优良性,并可以在之前凤凰城开始为任何请求服务。
答案 0 :(得分:3)
您可以在启动时在Repo
的{{1}}和Endpoint
主管之间启动工作人员:
my_app/application.ex
并创建文件# Define workers and child supervisors to be supervised
children = [
# Start the Ecto repository
supervisor(MyApp.Repo, []),
# The new worker
worker(MyApp.DoSomething, [], restart: :temporary),
# Start the endpoint when the application starts
supervisor(MyAppWeb.Endpoint, []),
# Start your own worker by calling: MyApp.Worker.start_link(arg1, arg2, arg3)
# worker(MyApp.Worker, [arg1, arg2, arg3]),
]
:
my_app/do_something.ex
在启动时,您应该在10秒的延迟后看到一些有关用户的信息:defmodule MyApp.DoSomething do
use GenServer
def start_link do
GenServer.start_link(__MODULE__, %{})
end
@impl true
def init(state) do
user = MyApp.Accounts.get_user!(1)
IO.inspect user
Process.sleep(10_000)
IO.inspect "Done sleeping"
# Process will send :timeout to self after 1 second
{:ok, state, 1_000}
end
@impl true
def handle_info(:timeout, state) do
# Stop this process, because it's temporary it will not be restarted
IO.inspect "Terminating DoSomething"
{:stop, :normal, state}
end
end
。
我不确定100%是否是这样做的最好和最安全的方法(也许根本不需要GenServer吗?),但是它确实有效。工作区中可以使用该存储库,并且端点Running MyAppWeb.Endpoint with Cowboy using http://0.0.0.0:4000
返回之前不会启动。
编辑:我已经更新了代码,以(希望)在完成后正确地关闭该过程。
答案 1 :(得分:1)
除了@zwippie很棒的答案外,我对自己的问题也有自己的答案,这是更通用的OTP标准,但我的却更简单,可以在某些情况下使用。
要在Phoenix端点开始服务请求之前立即调用该函数,我们可以从应用程序的Endpoint模块的init()回调中调用该函数,在Ecto.Repo.Supervisor启动Ecto.Repo工作程序之后立即调用该函数
因此,如果我们具有:my_app应用程序,则可以打开lib / my_app_web / endpoint.ex文件,在其中找到回调函数init()并从那里调用一些函数。
答案 2 :(得分:0)
This nice post还总结了第三种方法,即使用Task
模块。这样省去了编写完整的Genserver的麻烦:
defmodule Danny.Application do
use Application
# ...
def start(_type, _args) do
children = [
supervisor(Danny.Repo, []),
# ...
worker(Task, [&CacheWarmer.warm/0], restart: :temporary) # this worker starts, does its thing and dies
# ...
]
opts = [strategy: :one_for_one, name: Danny.Supervisor]
Supervisor.start_link(children, opts)
end
end
定义一个模块:
defmodule CacheWarmer do
import Logger, only: [debug: 1]
def warm do
# warming the caches
debug "warming the cache"
# ...
debug "finished warming the cache, shutting down"
end
end
请注意,your_app.ex
中唯一的附加行是:worker(Task, [&CacheWarmer.warm/0], restart: :temporary)