在初始化 Erlang 主管进程时添加 gen_event 个处理程序
Adding gen_event handlers while initializing an Erlang supervisor process
我正在学习 Erlang,并且能够相对有效地找到答案并制定出大多数问题的解决方案,但是在解决这个问题上花费了无法接受的时间:
将处理程序添加到由主管进程启动的 gen_event 模块的正确方法是什么?到目前为止,在我的探索中,我已经能够设置流程、gen_servers、主管(启动 gen_servers)和 gen_event 模块,但我尝试添加的所有内容实际上都是gen_event 的处理程序使我的主管进程崩溃 — 有时甚至是我的 shell!!
主管模块:
-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,但从未命中 'osc_event_server'
的 init
块
- 没有实际的事件处理程序附加到 gen_event。 "which_handlers" 和尝试发送消息都证实了这一点。
我想合并的两件事:
- 将特定的事件处理程序(例如,"send_osc")附加到我的 gen_event 进程中……希望来自主管代码
- 将初始化参数传递给osc_event_server模块;我希望至少能够指定 UDP 服务器的端口(而不是硬接线“8980”),并提供我希望我的进程与之通信的远程 UDP 服务器的 IP+端口。
非常感谢。随意批评你看到的任何东西......例如,我的整个方法 :) 就我目前所了解的 Erlang 而言,我敢肯定,与我使用的 Erlang 的数量相比,这算不了什么 误解.
您应该将 gen_event
进程视为节点上存在的一种服务。通常你会给它一个名字,然后用这个名字和它交谈。在您这样做之前,它只是一段独立的代码。
这意味着如果你想添加处理程序,鉴于你不能 运行 supervisor 中的任意代码来完成它,最简单的方法是让你的 supervisor 产生一个兄弟进程在 之后,gen_event
进程准备就绪。
将新兄弟标记为 transient
或 temporary
,让它成为 gen_server
或 supervisor_bridge
工人,并为其命名和处理 gen_event
。小工人应该添加处理程序。然后它可以因 normal
原因关闭,或者如果需要,监督处理程序以防它们崩溃以重新添加它们。
我正在学习 Erlang,并且能够相对有效地找到答案并制定出大多数问题的解决方案,但是在解决这个问题上花费了无法接受的时间:
将处理程序添加到由主管进程启动的 gen_event 模块的正确方法是什么?到目前为止,在我的探索中,我已经能够设置流程、gen_servers、主管(启动 gen_servers)和 gen_event 模块,但我尝试添加的所有内容实际上都是gen_event 的处理程序使我的主管进程崩溃 — 有时甚至是我的 shell!!
主管模块:
-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,但从未命中 'osc_event_server' 的
- 没有实际的事件处理程序附加到 gen_event。 "which_handlers" 和尝试发送消息都证实了这一点。
init
块
我想合并的两件事:
- 将特定的事件处理程序(例如,"send_osc")附加到我的 gen_event 进程中……希望来自主管代码
- 将初始化参数传递给osc_event_server模块;我希望至少能够指定 UDP 服务器的端口(而不是硬接线“8980”),并提供我希望我的进程与之通信的远程 UDP 服务器的 IP+端口。
非常感谢。随意批评你看到的任何东西......例如,我的整个方法 :) 就我目前所了解的 Erlang 而言,我敢肯定,与我使用的 Erlang 的数量相比,这算不了什么 误解.
您应该将 gen_event
进程视为节点上存在的一种服务。通常你会给它一个名字,然后用这个名字和它交谈。在您这样做之前,它只是一段独立的代码。
这意味着如果你想添加处理程序,鉴于你不能 运行 supervisor 中的任意代码来完成它,最简单的方法是让你的 supervisor 产生一个兄弟进程在 之后,gen_event
进程准备就绪。
将新兄弟标记为 transient
或 temporary
,让它成为 gen_server
或 supervisor_bridge
工人,并为其命名和处理 gen_event
。小工人应该添加处理程序。然后它可以因 normal
原因关闭,或者如果需要,监督处理程序以防它们崩溃以重新添加它们。