哪里可以在Elixir/Mix/Phoenix应用程序中添加服务/初始化代码?

问题描述:

我有一个Elixir/Mix应用程序(也是凤凰,但也有很多非凤凰的东西),我想知道什么是“启动”代码的最佳实践,例如动态添加孩子给主管,发射“我还活着!” ping或其他你想在启动后立即发生的事情。哪里可以在Elixir/Mix/Phoenix应用程序中添加服务/初始化代码?

一个显而易见的地方是Application文件,但预期的回报是从Supervisor.start_link(children, opts)返回。因此,例如,在凤凰城的应用程序,我可以这样做:

defmodule MyApp do 
    use Application 

    def start(_type, _args) do 
    import Supervisor.Spec 

    children = [ 
     supervisor(MyApp.Repo, []), 
     supervisor(MyApp.Endpoint, []), 
     supervisor(MyApp.DynamicSupervisorThingy, []) 
    ] 
    opts = [strategy: :one_for_one, name: MyApp.Supervisor] 
    start_val = Supervisor.start_link(children, opts) 



    # --- Put things right here that I want to start ---- 
    MyApp.DynamicSupervisorThingy.add_children_dynamically() 
    MyApp.SomeModule.do_some_thingy() 
    MyApp.OtherModule.send_some_pings() 
    if MIX_ENV == :prod do 
     MyApp.YetAnother.prod_stuff_i_dont_want_in_dev() 
    end 


    start_val 
    end 
end 

这似乎是错误的,但我想不出我应该可以把这个代码在哪里。

这完全没问题。您的Phoenix应用程序只是一款OTP应用程序,您可以根据需要自行拍摄脚部。 Application.start只是预期一个{:ok, pid}元组,它基本上是应用程序的顶层过程。

我通常首先放置自定义启动代码,然后设置主管理规范并启动该管理程序 - 请注意,如果您在启动“动态管理程序”和添加应用程序之间订购依赖关系,就好像它是上面的情况,你可能会因为时间原因而失去 - 我会在其规范中正确配置该主管,以便它可以在init回调中执行某些操作,但我不知道你的代码或需求。

在任何情况下,Application.start都是你的,只要你通过其信守合同:-)

+0

好知道,尤其是笔记关于把东西'init'。目前还不清楚我在'start_link'和'init'等等应该做什么/不该做什么。无论如何,我只是很高兴知道我没有在这里犯下一个可怕的罪。 – Micah

+1

start_link是“客户端”,init是“服务器端”。因此,通过init,您可以访问进程的内部以设置状态和内容。另外 - 请浏览一下GenServer/Supervisor代码(以及底层的Erlang实现)。它不是超级复杂的,可以让你对发动机罩下发生的事情有很好的见解:) – cdegroot