2017-09-11 105 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

相關問題