2015-03-03 15 views
8

Durch den Supervisor and Application Teil des Getting Started-Tutorials arbeitend, schreibe ich einen Komponententest für das Supervision Tree-Problem an der Unterseite. Ich versuchte, den Top-Level-Supervisor starten, aber es konnte nicht mit diesem Fehler:Wie finde ich die Arbeiter in meiner Elixir-Anwendung?

1) test all buckets die if registry dies (KV.SupervisorTest) 
    test/kv/supervisor_test.exs:4 
    ** (EXIT from #PID<0.111.0>) shutdown: failed to start child: GenEvent 
     ** (EXIT) already started: #PID<0.75.0> 

Anscheinend ist der App bereits gestartet, so muß ich den Zugang zu seinem Arbeitsprozesse erhalten. Ich könnte Supervisor.which_children verwenden, um sie zu bekommen, wenn ich den Supervisor hätte. Um das zu bekommen, vielleicht würde es helfen, die laufenden kv Anwendung haben:

iex(28)> kvpid = :application.info[:running][:kv] 
#PID<0.77.0> 

So, jetzt ich die PID für die App haben. Gibt es eine Möglichkeit, den Root-Supervisor-Prozess von diesem zu erhalten, oder muss ich ihn manuell irgendwo registrieren, um von dem Test zu kommen?

Oder gibt es eine Möglichkeit, die Arbeiter direkt von ihren Namen zu bekommen? Ich habe versucht, :erlang.whereis aber es findet nicht den Arbeiter:

iex(33)> :erlang.whereis KV.Registry 
:undefined 

ich direkt den Namen des Moduls versucht, mit, aber das funktioniert auch nicht:

test "all buckets die if registry dies" do 
    reg = KV.Registry 
    KV.Registry.create(reg, "shopping") 
    {:ok, shopping_bucket} = KV.Registry.lookup(reg, "shopping") 

    Process.exit(reg, :shutdown) 
    assert_receive {:exit, "shopping", ^shopping_bucket} 
end 

Es schlägt mit diesem Fehler:

1) test all buckets die if registry dies (KV.SupervisorTest) 
    test/kv/supervisor_test.exs:4 
    ** (ArgumentError) argument error 
    stacktrace: 
    :erlang.send(KV.Registry, {:"$gen_cast", {:create, "shopping"}}) 
    (elixir) lib/gen_server.ex:424: GenServer.do_send/2 
    test/kv/supervisor_test.exs:6 

The code is up on github.

+0

Um die Verzweigung für diese Frage zu erhalten, müssen Sie diesen Schritt hinzufügen: '$ git checkout -b s_o_question Herkunft/s_o_find_worker_question ' – ijt

Antwort

7

Sie können KV.Registry nicht finden, da ein Tippfehler in Ihrem Code vorhanden ist. Sie rufen:

worker(KV.Registry, [@manager_name, [name: @registry_name]]) 

aber die Definition ist:

def start_link(event_manager, buckets_supervisor, opts \\ []) do 

So passieren Sie [Name: KV.Registry] als buckets_supervisor, entscheidet sich ist [] und Ihre Arbeiter daher nicht registriert ist unter dem Namen KV .Registrierung.

Versuchen Sie diesen Patch: https://github.com/mprymek/kv/commit/03ce2e4e5ab4287db2fab6de0bb1aeaf0226346f

iex(1)> :erlang.whereis KV.Registry 
#PID<0.111.0> 
+0

P.S. Wenn Ihr Code korrekt funktioniert, hängt dies von einigen Argumenten ab. Wenn Sie definiert haben, dass Sie als "def start_link (event_manager, buckets_supervisor, opts)" funktionieren, würde dies nicht passieren. –

+0

Das Ändern der Worker-Zeile hat folgendes bewirkt: 'worker (KV.Registry, [@Manager_name, @Bucket_Suppenname, [Name: @registry_name]])' – ijt

1

Nachdem ich Ihr Repo geklont habe, habe ich mich umgesehen. Ich konnte die Anwendung nicht starten. Normalerweise Elixir-Anwendungen können von der Kommandozeile gestartet werden, indem Sie:

iex -S mix 

Aber wenn ich die Anwendung lief bekam ich folgende Fehlermeldung:

** (Mix) Could not start application kv: exited in: KV.start(:normal, []) 
** (EXIT) an exception was raised: 
    ** (UndefinedFunctionError) undefined function: KV.Supervisor.start_link/0 (module KV.Supervisor is not available) 
     KV.Supervisor.start_link() 
     (kernel) application_master.erl:272: :application_master.start_it_old/4 

Das bedeutet, dass in lib/kv.ex in Zeile 5 der Anwendung Marken ein Anruf an einen Supervisor namens KV.Supervisor. Ich schaute auf Ihren Code und kein Modul hat diesen Namen, aber ich sehe, dass Sie Modul verwenden das Supervisor-Verhalten mit dem Namen KV.Bucket.Supervisor.

Sie ein Modul benötigen entweder definieren benannte KV.Supervisor, die das Supervisor Verhalten implementiert, oder Update-Linie 5 in lib/kv.ex so nennt es KV.Bucket.Supervisor.start_link statt KV.Supervisor.start_link.

Sobald Sie das tun, sollten Sie die Prozesse der Lage sein, alle Vorgesetzten von betreut zu bekommen Aufruf dieser:

Supervisor.which_children(KV.Supervisor) # Pass in the name of your supervisor module 

hoffe, das hilft!

+0

KV.Supervisor wird ab Zeile 42 hier definiert: https://github.com/ijt /kv/blob/s_o_find_worker_question/lib/kv/supervisor.ex. Ich bin mir nicht sicher ob ich das verstehe. – ijt

+0

Es gibt noch einen weiteren Schritt beim Klonen des Repos. Sie müssen auch den Zweig auschecken: git checkout -b s_o_question Herkunft/s_o_find_worker_question. – ijt

6

Wenn Sie den Supervisor starten sie einen Namen gegeben, können Sie alle Arbeiter erhalten mit:

Supervisor.which_children(MyApp.Supervisor) 

Was wahrscheinlich passiert ist, dass Sie versuchen, Start zwei worker(GenEvent, ...) und sie werden Ereignisse dupliziert haben. Wenn Sie die Option :id explizit übergeben, wird dies wahrscheinlich behoben.

+0

Folgendes passiert: 'iex (1)> Supervisor.which_children (KV.Supervisor) ** (exit) exited in: GenServer.call (KV.Supervisor,: which_children,: unendlich) ** (EXIT) kein Prozess (Elixier) lib/gen_server.ex: 356: GenServer.call/3' even obwohl ich sehen kann, dass der KV.Supervisor von einer Log-Nachricht gestartet wurde. Ich habe nur einen Aufruf an "worker (GenEvent, ...)". – ijt

+0

Ah, ich verstehe. Ich musste den Body KV.Supervisor.start_link in 'Supervisor.start_link (__ MODULE__,: ok, [Name: KV.Supervisor])' 'ändern. Jetzt funktioniert Ihr Snippet. – ijt

Verwandte Themen