2017-09-11 46 views
0

我正在尝试为调度程序应用程序(使用Elixir 1.5语法注释)设置监督树。该应用程序应该工作,使:如何将参数传递给:simple_one_for_one GenServer以初始化状态

  • 应用程序启动使用注册表&调度监督员
  • 的SchedulerSupervisor靴,并允许通过start_child回调动态添加的儿童。这需要用于构建调度状态的初始化参数。
  • 调度程序在初始化时将其名称注册到注册中心,并使用一个包含状态的结构进行初始化(调度程序具有操纵调度的功能,但与我遇到的问题无关)。

如果我传递任何参数,我能得到这个工作 - 创建没有登记表,以及我在创建后修改状态。一旦我尝试添加参数,系统出错 - 我知道这只是我的一个语法误解,但我不能为我的生活弄清楚我做错了什么。我还没有在这里找到这些文档非常有用,我试着从GH,GH Gists和在线文章中复制和修改示例,但是我无法使其工作。

当前设置 - 理想我想要通过idperiodtargets作为参数传递给start_child,但可以甚至可以将其与一个参数不工作,所以只用一个坚持,直到我能得到它正在运行:

的应用:

defmodule Assay.Application do 
    use Application 

    def start(_type, _args) do 
    children = [ 
     {Assay.SchedulerSupervisor, []}, 
     {Registry, keys: :unique, name: Assay.Scheduler.Registry} 
    ] 

    opts = [strategy: :one_for_all, name: Assay.Supervisor] 
    Supervisor.start_link(children, opts) 
    end 
end 

主管:

defmodule Assay.SchedulerSupervisor do 
    use Supervisor 

    @name Assay.SchedulerSupervisor 

    def start_link(_args) do 
     Supervisor.start_link(__MODULE__, :ok, name: @name) 
    end 

    def start_schedule(id) do 
     Supervisor.start_child(@name, [id]) 
    end 

    def init(_) do 
     Supervisor.init([Assay.Scheduler], [strategy: :simple_one_for_one, name: @name]) 
    end 
end 

钍ËGenServer(只显示相关的初始化函数)

defmodule Assay.Scheduler do 
    use GenServer 
    alias Assay.Scheduler 
    require Logger 

    defstruct targets: [], period: 60_000, id: nil, active: false 

    def start_link(id) do 
     GenServer.start_link(__MODULE__, [id], [name: via_tuple(id)]) 
    end 

    def init([id]) do 
     Logger.info "starting a new #{__MODULE__} with id #{id}" 
     {:ok, %Scheduler{id: id}} 
    end 
end 

编辑:实际的错误可能会帮助 - 我可以看到ARGS是错误的,我只是不明白,为什么:

{:error, 
{:EXIT, 
    {:undef, 
    [{Assay.Scheduler, :start_link, [[], 1], []}, 
    {:supervisor, :do_start_child_i, 3, [file: 'supervisor.erl', line: 381]}, 
    {:supervisor, :handle_call, 3, [file: 'supervisor.erl', line: 406]}, 
    {:gen_server, :try_handle_call, 4, [file: 'gen_server.erl', line: 636]}, 
    {:gen_server, :handle_msg, 6, [file: 'gen_server.erl', line: 665]}, 
    {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 247]}]}}} 
+0

什么是你得到确切的错误? – Dogbert

+0

ah,对不起,添加了日志错误信息@Dogbert – DanCouper

+0

你确定这是问题中代码的错误信息吗?您没有将60000传递给start_child,但它在错误消息中。 – Dogbert

回答

4

对于:simple_one_for_one主管Supervisor.start_child使用在“子规范”中指定的参数给出的参数来调用启动函数。当使用Supervisor.init时,子规格取自Elixir 1.5中模块的child_spec/1函数。由于您使用的GenServer,而不是指定自定义启动功能和[]传递给child_spec/1,这defaults to[[]]这意味着你的函数结束了被称为有两个参数,[]1如果id1,你会得到一个未定义的函数错误。

你可以明确地说你不想GenServer提供任何参数来启动功能child_spec通过改变

use GenServer 

use GenServer, start: {__MODULE__, :start_link, []} 

解决这个问题现在功能将正确调用,只有一个参数,它将是id

IO.inspect Assay.SchedulerSupervisor.start_link [] 
IO.inspect Assay.SchedulerSupervisor.start_schedule 12 

会打印:

{:ok, #PID<0.82.0>} 
[info] starting a new Elixir.Assay.Scheduler with id 12 
{:ok, #PID<0.83.0>} 
+0

太棒了,谢谢。我发现这些文档对此非常不清楚(通过GitHub的问题进行挖掘,似乎去年DynamicSupervisor被提出时对它们的讨论还不清楚),现在变得更有意义 – DanCouper

相关问题