Захотелось получить в Erlang'е pubsub — процессы могут «подписываться» у некоторого «хаба» и дальше получать копии сообщений, которые получает этот хаб.
Я знаю про gen_event, но это мне не подходит — там события обрабатываются в одном процессе event manager'а, а я хочу, чтобы все подписчики были в своих, независимых процессах. Вдобавок к этому я не очень врубился в то, как заставить супервайзоры работать с обработчиками у gen_event, а факт того, что обработчики могут падать и их надо перезапускать — однозначен.
В гугле все, увы, забито результатами про Ejabberd и RabbitMQ. Хорошие вещи, но к сути моего вопроса никак не относящиеся — мне, по крайней мере, в обозримом будущем, не потребуется масштабируемое решение с внешним pubsub-сервером.
У меня возникла мысль, что pubsub довольно неплохо накладывается на дерево супервайзоров — достаточно супервайзора научить пересылать вниз по дереву сообщения. Собственно, я набросал вот такой behavior:
-module(dispatcher).
-extends(supervisor).
-export([notify/2, start_link/2, start_link/3, handle_cast/2]).
start_link(Mod, Args) ->
gen_server:start_link(dispatcher, {self, Mod, Args}, []).
start_link(SupName, Mod, Args) ->
gen_server:start_link(SupName, dispatcher, {SupName, Mod, Args}, []).
notify(Dispatcher, Message) ->
gen_server:cast(Dispatcher, {message, Message}).
handle_cast({message, Message}, State) ->
{reply, Children, State} = supervisor:handle_call(which_children, dummy, State),
Pids = lists:filter(fun(Pid) -> is_pid(Pid) end,
lists:map(fun({_Id, Child, _Type, _Modules}) -> Child end,
Children)),
[gen_server:cast(Pid, Message) || Pid <- Pids],
{noreply, State}.
И, пусть, вроде бы, все работает как положено — сообщения рассылаются, дети перезапускаются, я не уверен что это была хорошая идея. По крайней мере, я не уверен что до конца правильно понимаю как устроены супервайзоры в OTP, и что я все правильно реализовал.
Покритикуйте, пожалуйста, подход или предложите какую-нибудь альтернативу?
gen_server— в состоянии таскает список подписчиков, поhandle_cast/2рассылает им копии, все как по учебнику, за исключением усложнения дерева супервайзоров. А, как я понимаю, смотря на state супервайзора — он тоже, все что делает — таскает список детей, линкуется и поhandle_info/2да ждет сбоев ({'EXIT', ...}). Исходя из этого и решил накрутиться на supervisor. Только в гугле на "extending erlang behavior" ценного — аж целый один пост на SO, где предлагают проксировать руками, говоря что behavior'ы плохо расширяются. А у меня как-то работает — странно – drdaeman Aug 30 '11 at 16:39