Убедитесь, что процесс 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, Я прав? Есть идеи как его улучшить?

2 ответа

Решение

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

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

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

Другие вопросы по тегам