2015-12-18 72 views
4

我有靈藥一個簡單的事件處理程序使用GenEvent啓動相同的事件處理程序的多個實例藥劑

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 

我是一個新手,藥劑等正與文檔有點掙扎。我會很感激,如果有人能告訴我如何!謝謝。

回答

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 

測試一個消息e爲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: []} 
+0

謝謝你。也許我不太瞭解你的答案,但我試圖向多個處理程序(都是相同的)播放單個事件;一個pubsub機制。所以我不關心過濾出特定的消息。要做到這一點,我需要使用相同的模塊作爲事件處理程序,並將其作爲{模塊,編號}傳遞...在這裏解釋:https://github.com/elixir-lang/elixir/issues/3760但它doesn對我來說沒有任何意義! –

+1

好吧,我想我明白了。上面的代碼,過濾和所有,也可以解決您的問題。我想你使用'id'作爲頻道的名字。在這種情況下,每當進程需要訂閱特定「id」的事件時,只需添加一個具有該ID的新處理程序。訣竅是給處理程序一個與其他處理程序不同的ID:'GenEvent.add_handler manager {MyHandler,handler_id} {id,[]}''。這將防止返回'{:error,:already_present}' –

+0

是的。我想我們的信息只是越過了! –

4

所以事實證明,多個處理程序添加到同一個經理,你需要沿着線的東西:

GenEvent.add_handler(:myManager, {myHandler, :id1}, []) 

我把所有的爭論都搞砸了 - 感謝Elixir懈怠頻道上精彩的@true_droid。

相關問題