我使用GenEvent
在elixir中有一个简单的事件处理程序:
defmodule myHandler do
use GenEvent
#Callback
def handle_event {:message, x}, state do
IO.puts("Message value is #{x}")
{:ok, [x|state]}
end
end
我可以通常的方式启动一个处理程序和一个管理器:
{:ok, mgr} = GenEvent.start_link
myServer.start_link(mgr)
GenEvent.add_handler(mgr,myHandler, [])
但是,我想启动一个监督树,其中有N个处理程序,每个处理程序具有不同的ID,使用相同的管理器。
我试过了:
Gen.Event.add_handler({mgr, :id1},myHandler, [])
,没有运气!相反,我得到以下错误:
** (Mix) Could not start application : exited in: myApp.start(:normal, [])
** (EXIT) no connection to :id1
我是Elixir的新手,所以我正在努力处理文档。如果有人能告诉我如何,我将不胜感激!感谢。
答案 0 :(得分:4)
您可以在MyHandler
中始终拥有更复杂的状态:
defmodule MyHandler do
use GenEvent
def handle_event({:message, id, message}, {id, messages}) do
IO.puts "[ID: #{inspect id}] Message value is #{inspect message}."
{:ok, {id, [message | messages]}}
end
def handle_event(_, state) do
{:ok, state}
end
end
要按ID过滤消息,我会将消息结构更改为:
{:message, id, message}
如果您不这样做,每个处理程序都会打印相同的消息。我想这就是你想要这个ID的原因。
然后拥有id
,您可以执行以下操作:
{:ok, manager} = GenEvent.start_link
MyServer.start_link manager
GenEvent.add_handler manager, MyHandler, {id, []}
正如您所看到的,新状态是{id :: atom, messages :: list}
而不是简单的消息列表。
然后只需发送消息:
GenServer.sync_notify manager, {:message, id, message}
示例:
初始化经理:
iex(1)> {:ok, manager} = GenEvent.start_link
{:ok, #PID<0.75.0>}
添加处理程序:
iex(2)> GenEvent.add_handler manager, MyHandler, {:id0, []}
:ok
测试ID为:id0
的邮件并打印邮件:
iex(3)> GenEvent.sync_notify manager, {:message, :id0, "Hello"}
[ID: :id0] Message value is "Hello".
:ok
使用不存在的ID :id1
测试邮件并且它不会打印任何内容:
iex(4)> GenEvent.sync_notify manager, {:message, :id1, "Hello"}
:ok
你去吧。我希望这会有所帮助:)
P.S:如果您的州太复杂,您可以随时使用map:
%{id: id, messages: []}
答案 1 :(得分:4)
因此,事实证明,要向同一个经理添加多个处理程序,您需要以下内容:
GenEvent.add_handler(:myManager, {myHandler, :id1}, [])
我让这个论点搞得一团糟 - 感谢Elixir懒散频道上精彩的@true_droid。