[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'е? Может я вообще иду по неправильному пути?
Re: [erlang] Взаимодействие процессов - как организовать?
От: DmitryMe  
Дата: 22.08.09 14:20
Оценка:
А зачем gen_event? Есть же pidы процессов, которые можно регистрировать как глобально (для доступа из других нодов) или локально (для доступа на одном хосте. У меня сейчас похожая задача только у меня не gen_fsm'ы, а gen_server's, но думаю это не принципиально. Все сервисы регистрируются глобально, т.к. система будет разнесена по разным боксам. Предполагается что каждый процесс будет конфигурироваться списком имен процессов, на евенты которых он должен подписаться. Что он и делает посылая сообщение о подписке каждому из процессов, например в init методе.

Все вышесказанное ИМХО, т.к. я недавно на Erlang'e. Может есть какой-нибудь generic метод...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.