Добавление обработчиков gen_event при инициализации процесса супервизора Erlang
Я изучаю Erlang, и мне удается находить ответы и находить решения для большинства проблем относительно эффективно, но потратил недопустимое количество времени на разработку этого:
Как правильно добавить обработчики в модуль gen_event, который запускается процессом супервизора? В моем исследовании я до сих пор смог настроить процессы, gen_servers, супервизоры (которые запускают gen_servers) и модули gen_event, но все, что я пытался добавить обработчик в gen_event, приводит к сбою моего процесса супервизора - и иногда даже моя раковина!!
Модуль супервизора:
-module(sup).
-behaviour(supervisor).
%% API
-export([start_link/0, init/1]).
-export([stop/0]).
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
init(_) ->
EventServerSpec = #{
id => osc_event_server,
start => {gen_event, start_link, [{local, osc_server}]},
modules => dynamic
},
ChildSpecList = [EventServerSpec, child(frequency), child(bkpt_server)],
SupFlags = #{strategy => rest_for_one,
intensity => 2, period => 3600},
{ok, {SupFlags, ChildSpecList}}.
child(Module) ->
#{id => Module,
start => {Module, start_link, []},
restart => permanent,
shutdown => 2000,
type => worker,
modules => [Module]}.
… И некоторые кусочки из модуля gen_event, osc_event_server (надеюсь, соответствующие!)
...
init([]) ->
{ok, Socket} = gen_udp:open(8980, [binary, {active, false}]),
{ok, #{socket => Socket, target_port => get_target_port()}}.
...
handle_event({send_osc, Path, Data}, State) ->
TargetPort = maps:get(target_port, State),
Socket = maps:get(socket, State),
sendMessage(Socket, TargetPort, Path, Data),
{ok, State};
...
Как бы плохо я не понимал поведение gen_event, я не сильно удивлен результатом выполнения кода, включающего следующие фрагменты:
- запускается без сбоев
- он запускает gen_event и создает для него ссылочный Pid, но никогда не срабатывает
init
блок 'osc_event_server' - к gen_event не привязаны фактические обработчики событий. И "which_handlers", и попытки отправки сообщений подтверждают это.
Две вещи, которые я хотел бы включить:
- присоединить определенные обработчики событий (например, "send_osc") к моему процессу gen_event… возможно, из кода супервизора
- передать аргументы инициализации в модуль osc_event_server; Я хочу иметь возможность, по крайней мере, указать порт для UDP-сервера (вместо аппаратного "8980") и указать порт IP+ удаленного UDP-сервера, с которым я хочу, чтобы мой процесс связывался.
Спасибо большое. Не стесняйтесь критиковать все, что вы видите... например, весь мой подход:) Столько Эрланга, сколько я понял на данный момент, я уверен, что это ничто, по сравнению с количеством Эрланга, которое я неправильно понимаю.
1 ответ
Вы должны рассмотреть gen_event
Процесс как вид службы, которая существует на вашем узле. Обычно вы называете это имя и используете это имя, чтобы поговорить с ним. Пока вы этого не сделаете, это маленький отдельный кусок кода.
Это означает, что если вы хотите добавить обработчики, учитывая, что вы не можете запустить произвольный код в супервизоре, чтобы сделать это, самый простой способ сделать это - заставить вашего супервизора порождать процесс родственного брата после gen_event
процесс готов.
Отметить нового брата как transient
или же temporary
пусть будет немного gen_server
или же supervisor_bridge
рабочий, и дать ему имя и обработчики gen_event
, Маленький рабочий должен добавить обработчики. Затем он может закрыться с разумом normal
или, если необходимо, контролируйте обработчики в случае их сбоя, чтобы повторно добавить их.