PI

ВСТУП

Модуль n2o_pi призначений для створення та відстеження контрольованих процесів у всіх додатках, використовуючи будь-які ETS таблиці. Будь-який контрольований процес у N2O створюється за допомогою n2o_pi, в тому числі: кільцеві віртуальні вузли, таймери, авторизація, процеси веб-сторінок, тестові процеси та інші сервіси. Циклічний процес всередині протокольного обробника info/2 створює нові асинхронні процеси proc/2 у випадку трудоємких операцій, тому що обробник протоколу є критичним місцем, і його слід обробляти якомога швидше.

CALLBACK

proc(term(),#pi{}) -> #ok{} | #reply{}.

proc/2 — це колбек, який буде викликано при кожному виклику gen_server'а: handle_call, handle_cast і handle_info, його init та terminate. Колбек повертає #ok як початковий стан процесу (який також є #pi{}), або його відповідь на gen_server:call/2 з новим станом, включеним в #reply.

ПРИКЛАД

Приклад буквальної реалізації таймера N2O, який позначає недійсними відповідні записи в кеш-таблиці, яка використовується для змінних сесії.

Лістинг 1. Перевірка валідності кешу по таймеру
proc(init,#pi{}=Async) -> {ok,Async#pi{state=timer(ping())}}; proc({timer,ping},#pi{state=Timer}=Async) -> erlang:cancel_timer(Timer), io:format("n2o Timer: ~p\r~n",[ping]), n2o:invalidate_cache(caching), {reply,ok,Async#pi{state=timer_restart(ping())}}. timer(Diff) -> {X,Y,Z} = Diff, erlang:send_after(1000*(Z+60*Y+60*60*X),self(),{timer,ping}). ping() -> application:get_env(n2o,timer,{0,1,0}).
Лістинг 1. Перевірка валідності кешу по таймеру
> n2o_pi:start(#pi{ module=n2o, table=caching, sup=n2o, state=[], name="timer"}).

Головне призначення n2o_pi — створювати такі процеси з однієї функції proc/2, та відстежувати pid в ETS таблиці, які визначаються під час ініціалізації процесу #pi{}.

Лістинг 2. Розуміння n2o_pi
1> supervisor:which_children(n2o). [{{ring,4},<0.1661.0>,worker,[n2o_mqtt]}, {{ring,3},<0.1655.0>,worker,[n2o_mqtt]}, {{ring,2},<0.1653.0>,worker,[n2o_mqtt]}, {{ring,1},<0.1651.0v,worker,[n2o_mqtt]}, {{caching,"timer"},<0.1604.0>,worker,[n2o]}] 2> ets:tab2list(ring). [{{ring,4},infinity,<0.1661.0>}, {{ring,1},infinity,<0.1651.0>}, {{ring,2},infinity,<0.1653.0>}, {{ring,3},infinity,<0.1655.0>}] 3> ets:tab2list(caching). [{{caching,"timer"},infinity,<0.1604.0>}] 4> n2o_pi:send(caching,"timer",{timer,ping}). n2o Timer: ping ok 5> n2o_pi:pid(caching,"timer"). <0.1604.0>

Записи (Records)

Кожен процес керується його протоколом, який насправді є сукупністю повідомлень протоколу. Хоча n2o_pi загалом не обмежує повідомлення протоколу, однак він визначає тип стану процесу, запис #pi{}.

Лістинг 3. Erlang/OTP Records
#ok { code = [] :: [] | #pi{} }. #error { code = [] :: [] | term() }. #reply { data = [] :: [] | term() , code = [] :: [] | #pi{} }.

По замовчуванню, в N2O кожне поле повідомлення протоколу повинно бути [].

Лістинг 4. N2O Records
-record(pi, { name :: atom(), table :: ets:tid(), sup :: atom(), module :: atom(), state :: term() }).
  • name — ім'я процесу, ключ у контрольованому ланцюжку.
  • module — назва модуля, в якому розміщено proc/2.
  • table — назва ETS таблиці, де зберігається кеш pids.
  • sup — додаток, в якому буде створено контрольовані процеси.
  • state — стан запущеного контрольованого процесу.

API

start(#pi{}) -> {pid(),term()} | #error{}.

Запускає функцію proc/2 всередині контрольованого процесу.

stop(Class,Name) -> #pi{} | #error{}.

Зупиняє спостереження за процесом та вбиває цей процес.

restart(Class,Name) -> {pid(),term()} | #error{} | #pi{}.

Пробує завершити процес. У разу успіху запускає новий, інакше повертає помилку.

send(Class,Name,term()) -> term().

Надсилає повідомлення, отримане з таблиці Class з ключем Name, gen_call на обробку. Повертає відповідь gen_server:call.

pid(Class,Name) -> pid().

Повертає pid, який зберігався під час ініціалізації процесу в таблиці Class з ключем Name.

Лістинг 5. Сумісність з gen_server.
1> n2o_pi:pid(caching,"timer") ! {timer,ping}. n2o Timer: ping {timer,ping} 2> n2o_pi:send(caching,"timer", {timer,ping}). n2o Timer: ping ok 3> gen_server:call( n2o_pi:pid(caching,"timer"), {timer,ping}). n2o Timer: ping ok

Цей модуль може бути пов'язаним з: n2o, n2o_proto, n2o_mqtt.