簡體   English   中英

Phoenix應用啟動時的調用功能

[英]Calling function on Phoenix app start

在Phoenix應用程序啟動時,調用該函數從數據庫加載一些數據的最簡單方法是什么? 因此,我需要我的函數擁有Ecto.Query優良性,並在Phoenix開始處理任何請求之前調用它。

您可以在啟動時在RepoEndpoint主管之間的my_app/application.ex中啟動工作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

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

在啟動時,您應該在10秒鍾的延遲后看到一些有關用戶的信息: Running MyAppWeb.Endpoint with Cowboy using http://0.0.0.0:4000

我不確定這是否是最好,最安全的方法(也許根本不需要GenServer嗎?),但還是可以100%確定。 該回購在工作進程中可用,並且端點在init返回之前不會啟動。

編輯:我已經更新了代碼,以(希望)完成后正確關閉該過程。

除了@zwippie很棒的答案外,我還對自己的問題給出了自己的答案,這是更通用的OTP標准,但我的卻更簡單,可以在某些情況下使用。

要在Phoenix端點開始服務請求之前立即調用該函數,我們可以從應用程序的Endpoint模塊的init()回調中調用該函數,該回調在Ecto.Repo.Supervisor啟動Ecto.Repo工作器之后立即調用。

因此,如果我們有:my_app應用程序,則可以打開lib / my_app_web / endpoint.ex文件,在其中找到回調函數init()並從那里調用某些函數。

這篇不錯的文章還總結了第三種方法,即使用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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM