[erlang] Взаимодействие процессов - как организовать?
От: Васильич  
Дата: 17.08.09 09:44
Оценка:
Пишу некую систему на erlang'е, осваиваю язык. Столкнулся с одной проблемой, для которой пока не могу придумать удовлетворяющего меня решения.

В чем суть проблемы: обработкой данных в приложении занимается группа процессов. Большинство процессов представляют из себя машины состояний на основе gen_fsm, конечных состояний работы процесса может быть несколько (например, "операция завершилась успешно", "операцию нельзя выполнить для текущих условий" и т.д.). При этом каждый процесс универсален, то есть он выполняет какую-то вполне определенную задачу, определены контракты на входные и выходные параметры, а его результатами могут воспользоваться произвольные процессы, и эти связи определяет программист, конструируя общую схему взаимодействия процессов (очень напоминает dependency injection). Вопрос: как лучше организовать передачу событий между процессами, как правильно реализовать точки соприкосновения между ними?

Сначала я хотел использовать для этого gen_event. То есть, процессу при старте передается пид EventMgr'а, и когда процесс дойдет до какого-нибудь конечного состояния, то он просто будет вызывать gen_event:notify(EventMgr, ...). Соответственно, все потребители результатов работы этого процесса просто будут регистрировать свои обработчики в EventMgr'е. Схема красивая и архитектурно мне нравится, но у нее есть и свои минусы. Во-первых, для каждого процесса-потребителя придется писать отдельный модуль обработчика событий (behaviour(gen_event)), а может даже и не один. Кроме того, функционал gen_event для меня избыточен, fault tolerance не нужен, так как большинство обработчиков будут просто сводиться к gen_fsm:send_event(...).

Следующим решением было просто написать свой модуль, реализующий подписку на события. Модуль будет позволять сформировать список обработчиков, привязанных к определенным типам событий и вызывать их прямо в контексте процесса, который сгенерирует событие. Как-то так:

Запуск процесса с передачей ему информации о подписчиках (event_handler — мой самописный модуль):
Handlers = event_handler:add(handler2,
           event_handler:add(handler1, 
           event_handler:create())),

Config = [
    {param1, value1},
    ....
    {handlers, Handlers}],

some_process:start(Config).


Вызов обработчика внутри процесса:
some_state(Event, State) ->
    event_handler:notify(State#state.handlers).


Пока я склоняюсь к этому варианту.

Какие еще есть варианты связывания процессов в erlang'е? Может я вообще иду по неправильному пути?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.