3

Захотелось получить в 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, и что я все правильно реализовал.

Покритикуйте, пожалуйста, подход или предложите какую-нибудь альтернативу?

drdaeman
  • 9,253
  • 1
  • 20
  • 37
  • Репликатор идеально ложится на gen_server — в состоянии таскает список подписчиков, по handle_cast/2 рассылает им копии, все как по учебнику, за исключением усложнения дерева супервайзоров. А, как я понимаю, смотря на state супервайзора — он тоже, все что делает — таскает список детей, линкуется и по handle_info/2 да ждет сбоев ({'EXIT', ...}). Исходя из этого и решил накрутиться на supervisor. Только в гугле на "extending erlang behavior" ценного — аж целый один пост на SO, где предлагают проксировать руками, говоря что behavior'ы плохо расширяются. А у меня как-то работает — странно – drdaeman Aug 30 '11 at 16:39

0 Answers0