首页 > 解决方案 > 如何通过 Supervisor.init 启动命名代理?

问题描述

我有一个非常简单的混合应用程序(它是凤凰伞项目的一部分)。它甚至不包括业务逻辑流程。例如:

defmodule BGAdapter.Application do
  use Application

  def start(_type, _args) do
    children = [
      BGAdapter.LifeCycle # Agent
    ]

    Supervisor.start_link(children, strategy: :one_for_one, name: BGAdapter.Supervisor)
  end
end

Agent打了两次电话。一次put,第二次get。所以我想Agent BGAdapter.LifeCycle用 smth 替换单独的模块,例如:

defmodule BGAdapter.Application do
  use Application

  def start(_type, _args) do
    children = [
      { Agent, fn -> %{} end, name: BGAdapter.LifeCycle } # This does not work
    ]
...

错误是:

** (Mix) Could not start application bg_adapter: exited in: BGAdapter.Application.start(:normal, [])
    ** (EXIT) an exception was raised:
        ** (ArgumentError) supervisors expect each child to be one of the following:

  * a module
  * a {module, arg} tuple
  * a child specification as a map with at least the :id and :start fields
  * or a tuple with 6 elements generated by Supervisor.Spec (deprecated)

Got: {Agent, #Function<0.33439399/0 in BGAdapter.Application.start/2>, [name: BGAdapter.LifeCycle]}

我怎样才能开始Agent“内联”?

标签: elixir

解决方案


感谢@hauleth 在 Elixir-lang slack 中回答了这个问题。

正确的行是:

%{id: BGAdapter.LifeCycle, start: {Agent, :start_link, [fn -> %{} end, [name: BGAdapter.LifeCycle]]}}

申请文件:

defmodule BGAdapter.Application do
  use Application

  def start(_type, _args) do
    children = [
      %{
        id: BGAdapter.LifeCycle,
        start: {Agent, :start_link, [fn -> %{} end, [name: BGAdapter.LifeCycle]]}
      }
    ]

    Supervisor.start_link(children, strategy: :one_for_one, name: BGAdapter.Supervisor)
  end
end

我不确定,但我认为问题在于它Agent有自己的start(和start_link)格式。它没有得到执行。我的意思是GenServer.start(Impl, init_args, opts)-vsAgent.start(init_fn, opts)


推荐阅读