Tydzień temu stworzyliśmy Supervisor jako moduł. Osobny fragment kodu, który umożliwił nam zarządzanie PingPong.Server tak, że kiedy nam padł proces, automatycznie był on startowany. To wszystko dostajemy w elixir out-of-the-box. A dokładnie mówiąc w erlangu – zresztą dawałem linki do dokumentacji erlanga w tej sprawie.

Dziś zaś ten sam PingPong.Server wykorzystamy w skrypcie – bez modułu. Będzie nam dużo prościej niż ostatnio, gdyż znamy już znaczną część API i parametrów. Teraz wystarczy, że to oprogramujemy.

Supervisor w skrypcie

Zacznijmy o odpalenia iex z załadowanym modułem PingPongServer.exs:

iex PingPongServer.exes

Możemy sprawdzić czy dobrze załadowaliśmy nasz serwer podobnie jak w zeszłym tygodniu.

iex>PingPong.Server.start_link
iex>PingPong.Server.ping

Jak to zrobicie to ubijcie proces servera:

iex>Process.whereis(:pingpong) |> Process.exit(:kill)

Skoro wiemy, że nasz serwer PingPong działa, to możemy przystąpić do jego wykorzystania przez Supervisor. Jak pamiętacie, przy robieniu use Supervisor, następowało głównie wstrzyknięcie:

import Supervisor.Spec

Który udostępnia takie metody jak wroker, supervisor czy supervise. Zarówno worker jak i supervisor jest nam potrzebne by określić co nasze procesy dzieci mają robić. Czy to będzie praca nadzorowania innych procesów, czy też normalne wykonywanie pracy, nie ma znaczenia. Musimy jednak móc wywołać taką metodę. Można to zrobić za pomocą pełnej składki, lub skróconej (bez części Supervisor.Spec). Ja osobiście wolę skróconą. Pierwszym krokiem więc będzie zaimportowanie modułu Supervisor.Spec:

iex>import Supervisor.Spec

Mając już moduł dostępny, musimy określić listę procesów, które  mają być nadzorowane. W tym celu tworzymy listę procesów i przypasowujemy (pamiętacie pattern maching?:)) ją do zmiennej :

iex>children = [ worker(PingPong.Server, [])]

Teraz, możemy wystartować z naszym Supervisor za pomocą metody Supervisor.start_link/2:

start = Supervisor.start_link(children, strategy: :one_for_one)

Różnica w tym co my tutaj robimy a to co było tydzień temu jest taka, że nasz kod napotyka na guard z pattern matching, przez co wchodzimy do metody która:

  • wywołuje supervise, zwracający schemat nadzorcy
  • wywołuje start_link/3 podając dummy moduł jako pierwszy parameter

Dokładnie mówiąc, my wykonywaliśmy w zeszłym tygodniu takie o to kod:

Supervisor.start_link(__MODULE__, [])

Który trafiał pod start_link/3, gdzie trzeci parametr był opcjonalny. Zaś nasz teraźniejszy kod zamieniany jest na:

spec = Supervisor.Spec.supervise(children, options)
Supervisor.start_link(Supervisor.Default, spec, options)

Co też oznacza, że sami możemy tak napisać i będzie ok :)

W tym wypadku udaje nam się nie posiadać metody init/1, a wszystko przez nadpisaną metodę start_link/2.

To co my jeszcze zrobiliśmy to przypisaliśmy wynik start_link do zmiennej start. Zawiera ona tuple, który określi czy udało się nam wystartować nadzorcę i jak tak, jaki jest jego PID. Jakbyśmy chcieli, pobrać PID nadzorcy to:

iex>{ :ok, pid} = start

Tutaj ważne jest to by było :ok – inaczej może być :error, a ten ma prawo mieć inną strukturę lub inne wartości w tuple. Teraz możemy zrobić kilka rzeczy. Po pierwsze, możemy wysłać nasz ping:

iex>PingPong.Server.ping

Możemy także zrobić to samo w zeszłym tygodniu:

Process.whereis(:pingpong)
Process.whereis(:pingpong) |> Process.exit(:kill)
Process.whereis(:pingpong)
Process.whereis(:pingpong) |> Process.exit(:kill)
Process.whereis(:pingpong)

I zobaczyć, że nasz PID od serwera, ulega zmianie co ubicie, a to znaczy, że supervisor działa jak należy. A dzięki metodzie: Supervisor.count_children/1, możemy dowiedzieć się ile tych naszych procesów działa:

iex>Supervisor.count_children(pid)
%{active: 1, specs: 1, supervisors: 0, workers: 1}

Podsumowanie

Jak widać, nie jest trudno stworzyć Supervisor w iex. Wcale do tego moduł nie jest potrzebny. Za to łatwiej jest nam pewne rzeczy konfigurować i z miejsca możemy zobaczyć jak nasz kod działa i czy działa tak jak by chcemy. Wykorzystując wiedzę z tych dwóch postów na temat Supervisor, za tydzień stworzymy aplikację trochę bardziej zaawansowaną pod względem struktury drzewka children. Wszystko po to by za dwa tygodnie pobawić się pewną fajną funkcją :)

Do przeczytania za tydzień! :)

1 KOMENTARZ

Comments are closed.