【问题标题】:Is it possible to add a local event handler to a remote event manager是否可以将本地事件处理程序添加到远程事件管理器
【发布时间】:2017-06-07 14:46:55
【问题描述】:

我有一个在其自己的 Erlang 节点中运行的事件管理器。我想将它用作一个简单的事件代理,并让其他节点上的其他应用程序通过添加自己的事件处理程序来订阅它。

我的测试设置是这样的(抱歉缩进很糟糕)

运行时出现如下错误:

{'EXIT',{undef,[{event_handler_a,init,[[]],[]},
                {gen_event,server_add_handler,4,
                           [{file,"gen_event.erl"},{line,429}]},
                {gen_event,handle_msg,5,[{file,"gen_event.erl"},{line,270}]},
                {proc_lib,init_p_do_apply,3,
                          [{file,"proc_lib.erl"},{line,247}]}]}}

所以现在,我想知道我是否做错了什么,或者这种架构是不可能的。由于我的事件处理程序中的逻辑与我的应用程序完全相关,因此我更愿意将其保留在我的应用程序版本中。在我的事件管理器版本中为每个应用程序设置一个事件处理程序可能很快就会变得一团糟。

【问题讨论】:

  • 我对 gen_event 了解不多,但该错误看起来像 gen_event 试图调用 event_handler_a:init([]) 并且该模块或该函数未在该 Erlang 节点上定义/加载。
  • @Dogbert 我忘了这个。如果事件管理器从事件处理程序调用 init/1 回调,它将需要指定节点名称。不幸的是,文档显示add_handler(EventMgrRef, Handler, Args) -> ResultHandler = Module | {Module,Id}
  • 我认为你可以将其传递为Args,所以gen_event:add_handler(_, _, node1@host1)
  • 如果我正确理解发生了什么(我希望不是),我的应用程序调用add_handler/3,然后事件管理器回调init/1。如果是这种情况,在我的情况下,必须通过 rpc 完成回调才能工作。这将彻底破坏最初拥有经纪人的整个想法。
  • 来自the doc 向事件管理器EventMgrRef添加一个新的事件处理程序。事件管理器调用 Module:init/1 来启动事件处理程序及其内部状态。因此事件处理程序模块必须与事件管理器位于同一节点上。

标签: erlang erlang-otp


【解决方案1】:

不,这是不可能的。 gen_event 的工作方式与其他行为稍有不同,因为回调模块中的代码(作为参数传递给gen_event:add_handler/3 的代码)与事件管理器在相同 进程中运行。因此,如果事件管理器在远程节点上运行,事件处理程序将在同一节点上运行。

实现此目的的一种方法是创建一个事件处理程序回调模块,将事件转发到所需节点上的进程。然后你可以这样做:

gen_event:add_handler({event_manager, node1@host1}, my_event_forwarder, [self()]).

【讨论】:

  • 我就是这么想的。我也许还可以创建一个非常通用的处理程序,它将fun() 作为它的 init 参数,并将所有事件传递给这个fun()。订阅将是始终添加具有不同fun() 的相同处理程序模块以执行不同操作的问题。
  • 注意,定义fun的模块必须加载到调用它的节点上。
猜你喜欢
  • 1970-01-01
  • 2010-09-13
  • 2021-02-26
  • 2018-08-24
  • 2016-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多