Добавление обработчиков gen_event при инициализации процесса супервизора Erlang - PullRequest
1 голос
/ 19 апреля 2019

Я изучаю 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 Ответ

1 голос
/ 20 апреля 2019

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

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

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

...