Запуск нескольких экземпляров одного и того же обработчика событий в Elixir
У меня есть простой обработчик событий в эликсире, используя 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 обработчиков, каждый с разным идентификатором, используя тот же менеджер.
Я старался:
Gen.Event.add_handler({mgr, :id1},myHandler, [])
без везения! Вместо этого я получаю следующую ошибку:
** (Mix) Could not start application : exited in: myApp.start(:normal, [])
** (EXIT) no connection to :id1
Я новичок в Elixir и поэтому немного борюсь с документацией. Буду признателен, если кто-нибудь покажет мне как! Благодарю.
2 ответа
Вы всегда можете иметь более сложное состояние в 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
Чтобы отфильтровать сообщения по идентификатору, я бы изменил структуру сообщения на:
{:message, id, message}
Если вы этого не сделаете, каждый обработчик напечатает одно и то же сообщение. Я думаю, именно поэтому вы хотите, чтобы удостоверение личности.
Тогда имея 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
Протестируйте сообщение с идентификатором :id0
и печатает сообщение:
iex(3)> GenEvent.sync_notify manager, {:message, :id0, "Hello"}
[ID: :id0] Message value is "Hello".
:ok
Протестируйте сообщение с несуществующим идентификатором :id1
и это ничего не печатает:
iex(4)> GenEvent.sync_notify manager, {:message, :id1, "Hello"}
:ok
Вот и ты. Надеюсь, это поможет:)
PS: Если ваше состояние слишком сложное, вы всегда можете использовать карту:
%{id: id, messages: []}
Так что получается, что для добавления нескольких обработчиков в один и тот же менеджер вам нужно что-то вроде:
GenEvent.add_handler(:myManager, {myHandler, :id1}, [])
У меня был весь спор - благодаря замечательному @true_droid на слабом канале Elixir.