Добавление обработчиков 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", и попытки отправки сообщений подтверждают это.

Две вещи, которые я хотел бы включить:

  1. присоединить определенные обработчики событий (например, "send_osc") к моему процессу gen_event… возможно, из кода супервизора
  2. передать аргументы инициализации в модуль osc_event_server; Я хочу иметь возможность, по крайней мере, указать порт для UDP-сервера (вместо аппаратного "8980") и указать порт IP+ удаленного UDP-сервера, с которым я хочу, чтобы мой процесс связывался.

Спасибо большое. Не стесняйтесь критиковать все, что вы видите... например, весь мой подход:) Столько Эрланга, сколько я понял на данный момент, я уверен, что это ничто, по сравнению с количеством Эрланга, которое я неправильно понимаю.

1 ответ

Решение

Вы должны рассмотреть gen_event Процесс как вид службы, которая существует на вашем узле. Обычно вы называете это имя и используете это имя, чтобы поговорить с ним. Пока вы этого не сделаете, это маленький отдельный кусок кода.

Это означает, что если вы хотите добавить обработчики, учитывая, что вы не можете запустить произвольный код в супервизоре, чтобы сделать это, самый простой способ сделать это - заставить вашего супервизора порождать процесс родственного брата после gen_event процесс готов.

Отметить нового брата как transient или же temporaryпусть будет немного gen_server или же supervisor_bridge рабочий, и дать ему имя и обработчики gen_event, Маленький рабочий должен добавить обработчики. Затем он может закрыться с разумом normalили, если необходимо, контролируйте обработчики в случае их сбоя, чтобы повторно добавить их.

Другие вопросы по тегам