Убедитесь, что процесс gen_fsm/gen_server существует при отправке сообщения

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

%% DeviceId - process name

heartbeat(ApplicationKey, DeviceId, Timeout) ->
    ensure_session_started(ApplicationKey, DeviceId, Timeout),
    gen_fsm:send_event(DeviceId, {heartbeat, Timeout}).

ensure_session_started(ApplicationKey, DeviceId, Timeout) ->
    case session_server_sup:start_child(ApplicationKey, DeviceId, Timeout) of
        {ok, _Pid} -> {ok, running};
        {error, {already_started, _}} -> {ok, running};
        {error, Error} -> erlang:throw({error, {failed_to_start_session, Error}})
    end.

Я считаю, что это решение не идеально и, вероятно, имеет некоторые накладные расходы, но все же считаю, что оно менее подвержено гонкам, чем использование erlang:is_process_alive. Я прав? Есть идеи, как его улучшить?


person mkorszun    schedule 23.07.2013    source источник


Ответы (2)


Вы правы, подход erlang:is_process_alive/1 в этом сценарии бесполезен из-за состояния гонки.

Ваш пример работоспособен, и я видел его в дикой природе несколько раз. Обратите внимание, что это не гарантирует, что сообщение будет обработано. Чтобы быть уверенным в этом, вам нужно следить за своим приемником и получать от него подтверждение. Вот как это делается в gen_server:call/2.

person Paul Peregud    schedule 23.07.2013

С помощью gen_fsm:sync_send_event/2,3 вы можете отправлять события на ваш FSM и дождитесь ответа. Таким образом, вы можете сообщить вызывающему процессу, что его сообщение получено.

person lud    schedule 24.07.2013