2017-09-11 3 views
0

Ich versuche, eine Überwachungsstruktur für eine Scheduler-Anwendung einzurichten (beachten Sie die Elixir 1.5-Syntax). Die Anwendung sollte Arbeit, so dass:So übergeben Sie Argumente an: simple_one_for_one GenServer initialisiert den Status

  • Anwendung Stiefel mit einem Registry & der Scheduler Supervisor
  • Die SchedulerSupervisor Stiefel, und Kinder können dynamisch über das start_child Rückruf hinzugefügt werden. Dies erfordert die Initialisierungsargumente, die zum Erstellen des Zeitplanstatus verwendet werden.
  • Der Scheduler registriert bei der Initialisierung seinen Namen in der Registry und initialisiert ihn mit einer Struktur, die den Status enthält (Scheduler hat dann Funktionen zur Bearbeitung von Zeitplänen, aber das ist für das Problem, das ich habe, nicht relevant).

Wenn ich nicht keine Argumente übergeben, kann ich diese Arbeit bekommen - die Termine erstellt werden nicht registriert, und ich habe, um den Zustand nach der Erstellung zu ändern. Sobald ich versuche, Argumente hinzuzufügen, gehen die Systemfehler aus - ich weiß, dass es nur ein Syntaxmissverständnis von meiner Seite ist, aber ich kann nicht für das Leben von mir herausfinden, was ich falsch mache. Ich habe die Dokumentation hier nicht fürchterlich hilfreich gefunden, und ich habe versucht, Beispiele von GH, GH Gists und Artikeln online zu kopieren und zu modifizieren, aber ich kann es nicht zum Laufen bringen.

Aktuelle Setup - im Idealfall würde ich id, period und targets als Argumente an start_child übergeben will, kann aber nicht einmal mit einem einzigen Argumente bekommen arbeiten, also nur mit dem einem kleben, bis ich es läuft bekommen kann:

Die Anwendung:

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 

Der Betreuer:

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 

Th e GenServer (nur relevant Initialisierung Funktionen gezeigt)

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 

edit: tatsächliche Fehler kann helfen - ich, dass die args sind falsch sehen können, ich, warum können nicht herausfinden:

{: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

Was sind die genauen Fehler Sie bekommen? – Dogbert

+0

ah, sorry, protokollierte Fehlermeldung hinzugefügt @Dogbert – DanCouper

+0

Sind Sie sicher, dass das die Fehlermeldung für den Code in der Frage ist? Sie übergeben 60000 nicht an start_child, aber es ist dort in der Fehlermeldung. – Dogbert

Antwort

4

Für :simple_one_for_one Supervisors, Supervisor.start_child ruft die Startfunktion mit den Argumenten auf, die ihr mit den in der Child-Spezifikation angegebenen Argumenten übergeben werden. Bei Verwendung von Supervisor.init wird die untergeordnete Spezifikation von der Funktion child_spec/1 des Moduls in Elixir 1.5 übernommen. Da Sie mit GenServer und nicht die Angabe einer benutzerdefinierten Startfunktion und [] wird weitergegeben child_spec/1, diese defaults to[[]] was bedeutet, dass Ihre Funktion endet als mit zwei Argumenten aufgerufen, [] und 1 wenn die id1 ist und Sie erhalten eine nicht definierte Funktion Fehler .

Sie können dieses Problem beheben, indem Sie explizit sagen Sie nicht die GenServer alle Argumente in child_spec auf die Start-Funktion zur Verfügung stellen möchten, indem

Ändern
use GenServer 

zu

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

Nun wird die Funktion sein richtig benannt, mit nur einem Argument, welches die id sein wird.

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

drucken:

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

Fantastisch, danke. Ich fand die Dokumente sehr unklare darüber (graben durch GitHub Probleme und scheint, als ob einige Diskussion darüber unklar war, wenn DynamicSupervisor letztes Jahr vorgeschlagen wurde), macht jetzt viel mehr Sinn – DanCouper

Verwandte Themen