Phoenix应用启动时的调用功能

时间:2018-07-11 20:06:40

标签: elixir phoenix-framework ecto

调用Phoenix应用程序启动时从数据库加载一些数据的函数的最简单方法是什么?因此,我需要我的函数具有Ecto.Query优良性,并可以在之前凤凰城开始为任何请求服务。

3 个答案:

答案 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)