erlang - How to pass arguments to :simple_one_for_one GenServer to initialize state -
i trying set supervision tree scheduler application (note using elixir 1.5 syntax). application should work that:
- application boots registry & scheduler supervisor
- the schedulersupervisor boots, , allows children dynamically added via
start_child
callback. takes initialisation args used build schedule state. - the scheduler, on initialisation, registers name registry, , initialises struct holds state (scheduler has functions manipulating schedules, isn't relevant issue i'm having).
if don't pass arguments, can working - schedules created not registered, , have modify state after creation. try add arguments, system errors out - know it's syntax misunderstanding on part, cannot life of me figure out i'm doing wrong. haven't found docs terribly helpful here, , i've tried copying , modifying examples gh, gh gists , articles online, cannot work.
current setup - ideally want pass id
, period
, targets
arguments start_child
, can't working single argument, sticking 1 until can running:
the application:
defmodule assay.application use application def start(_type, _args) 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
the supervisor:
defmodule assay.schedulersupervisor use supervisor @name assay.schedulersupervisor def start_link(_args) supervisor.start_link(__module__, :ok, name: @name) end def start_schedule(id) supervisor.start_child(@name, [id]) end def init(_) supervisor.init([assay.scheduler], [strategy: :simple_one_for_one, name: @name]) end end
the genserver (only relevant initialisation functions shown)
defmodule assay.scheduler use genserver alias assay.scheduler require logger defstruct targets: [], period: 60_000, id: nil, active: false def start_link(id) genserver.start_link(__module__, [id], [name: via_tuple(id)]) end def init([id]) logger.info "starting new #{__module__} id #{id}" {:ok, %scheduler{id: id}} end end
edit: actual error might - can see args wrong, can't figure out why:
{: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]}]}}}
for :simple_one_for_one
supervisors, supervisor.start_child
calls start function arguments given arguments specified in child specification. when using supervisor.init
, child specification taken module's child_spec/1
function in elixir 1.5. since you're using genserver
, not specifying custom start function , []
passed child_spec/1
, defaults to [[]]
means function ends being called 2 arguments, []
, 1
if id
1
, undefined function error.
you can fix explicitly saying don't want genserver provide arguments start function in child_spec
changing
use genserver
to
use genserver, start: {__module__, :start_link, []}
now function called correctly, 1 argument, id
.
io.inspect assay.schedulersupervisor.start_link [] io.inspect assay.schedulersupervisor.start_schedule 12
will print:
{:ok, #pid<0.82.0>} [info] starting new elixir.assay.scheduler id 12 {:ok, #pid<0.83.0>}
Comments
Post a Comment