2017-01-23 47 views
2

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

我的测试设置是这样的(对不起可怕的压痕) enter image description here

运行此我得到这样一个错误:

{'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}]}]}} 

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

+1

我不知道很多关于'gen_event',但这个错误看起来像'gen_event'试图打电话'event_handler_a:初始化([])',要么该模块或该函数未在该Erlang节点上定义/加载。 – Dogbert

+0

@Dogbert我忘了这件事。如果事件管理器从事件处理程序调用init/1回调,则需要指定节点名称。不幸的是,doc显示 'add_handler(EventMgrRef,Handler,Args) - > Result' with'Handler = Module | {Module,Id}' – ITChap

+0

我想你可以通过'Args',所以'gen_event:add_handler(_,_,node1 @ host1)'。 – Dogbert

回答

5

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

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

gen_event:add_handler({event_manager, [email protected]}, my_event_forwarder, [self()]). 
+0

这就是我的想法。我也可以创建一个非常通用的处理函数,它将init()作为fun()的参数,并将所有事件传递给这个fun()。订阅将总是添加具有不同'fun()'的相同处理程序模块来完成不同的事情。 – ITChap

+1

请注意,fun中定义的模块必须加载到调用它的节点上。 – legoscia

相关问题