Убедитесь, что процесс 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 и ждать ответа. Таким образом, вы можете сообщить своему вызывающему процессу, что его сообщение было получено.