2015-03-03 29 views
8

Podczas pracy nad samouczkiem Wprowadzenie, piszę test jednostkowy dla problemu drzewa nadzoru na dole. Próbowałem rozpoczęciem przełożonego najwyższego poziomu, ale nie powiodło się z tego błędu:Jak znaleźć pracowników w mojej aplikacji Elixir?

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> 

Widocznie aplikacja jest już uruchomiona, więc muszę mieć dostęp do swoich procesów roboczych. Gdybym miał przełożonego, mógłbym skorzystać z pomocy Opiekuna. Aby dostać się, że może to pomóc, aby mieć uruchomiony kv aplikację:

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

Więc teraz mam PID dla aplikacji. Czy jest jakiś sposób, aby uzyskać od tego proces administratora root, czy muszę ręcznie zarejestrować go gdzieś, aby uzyskać z niego test?

Czy istnieje sposób na bezpośrednie pozyskanie pracowników od ich nazwisk? Próbowałem :erlang.whereis ale nie znajdzie pracownikowi:

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

Próbowałem za pomocą nazwy modułu bezpośrednio, ale to nie działa albo:

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 

nie powiedzie się z tego błędu:

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

Aby uzyskać oddział dla tego pytania, musisz dodać ten krok: '$ git checkout -b s_o_question origin/s_o_find_worker_question' – ijt

Odpowiedz

7

Nie możesz znaleźć KV.Registry, ponieważ w twoim kodzie jest literówka. Nazywasz:

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

ale definicja brzmi:

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

więc przechodzić [nazwa: KV.Registry] jako buckets_supervisor, wybiera to [] a pracownik nie jest zatem zarejestrowana pod nazwą KV .Rejestr.

Spróbuj patch: https://github.com/mprymek/kv/commit/03ce2e4e5ab4287db2fab6de0bb1aeaf0226346f

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

P.S. jeśli poprawne działanie twojego kodu zależy od jakiegoś argumentu, prawdopodobnie powinno być obowiązkowe. Jeśli zdefiniowałeś, że działasz jako "def start_link (event_manager, buckets_supervisor, opts)", to by się nie stało. –

+0

Zmiana linii robota spowodowała: 'worker (KV.Registry, [nazwa_manemu menedżera, @bucket_sup_name, [nazwa: @ nazwa_wystawy]])' – ijt

1

Po sklonowaniu twojego repo rozejrzałam się. Nie mogłem uruchomić aplikacji. aplikacje normalnie eliksiru może być uruchamiany z linii poleceń za pomocą polecenia:

iex -S mix 

Ale kiedy prowadził swoją aplikację mam następujący błąd:

** (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 

Oznacza to, że lib/kv.ex na linii 5 twoi uzależnia zastosowanie połączenie z przełożonym o nazwie KV.Supervisor. Spojrzałem na twój kod i żaden moduł nie ma tej nazwy, ale widzę, że masz moduł wykorzystujący zachowanie nadzorcy o nazwie KV.Bucket.Supervisor.

Trzeba będzie albo zdefiniować moduł o nazwie KV.Supervisor który implementuje zachowanie przełożonego lub aktualizacji linii 5 w lib/kv.ex tak nazywa to KV.Bucket.Supervisor.start_link zamiast KV.Supervisor.start_link.

Gdy to zrobisz, że powinieneś być w stanie uzyskać wszystkie procesy nadzorca nadzoruje, wywołując w ten sposób:

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

Nadzieja to pomaga!

+0

KV.Supervisor jest zdefiniowany począwszy od linii 42 tutaj: https://github.com/ijt /kv/blob/s_o_find_worker_question/lib/kv/supervisor.ex. Nie jestem pewien, czy rozumiem. – ijt

+0

Jest jeszcze jeden krok podczas klonowania repozytorium. Musisz również sprawdzić oddział: git checkout -b s_o_question origin/s_o_find_worker_question. – ijt

6

Jeśli zaczniesz przełożonego danego to nazwa, można uzyskać wszystkich pracowników z:

Supervisor.which_children(MyApp.Supervisor) 

Jakie jest prawdopodobieństwo dzieje jest to, że starają się uruchom dwa worker(GenEvent, ...) i będą miały zduplikowane zdarzenia. Przekazywanie jawnie opcji :id prawdopodobnie ją naprawi.

+0

Oto co się dzieje: 'iex (1)> Supervisor.which_children (KV.Supervisor) ** (exit) wyjście w: GenServer.call (KV.Supervisor,: which_children,: infinity) ** (EXIT) bez procesu (eliksir) lib/gen_server.ex: 356: GenServer.call/3' nawet chociaż widzę, że KV.Supervisor został uruchomiony z komunikatu dziennika. Mam tylko jedno połączenie do 'worker (GenEvent, ...)'. – ijt

+0

Ah, rozumiem. Musiałem zmienić ciało KV.Supervisor.start_link na 'Supervisor.start_link (__ MODULE__,: ok, [name: KV.Supervisor])'. Teraz twój snippet działa. – ijt

Powiązane problemy