У меня есть процесс, который нужно выполнять каждую работу каждые пятнадцать секунд. В настоящее время я делаю это так:
-behavior(gen_server). interval_milliseconds ()-> 15000. init()-> {ok, _State = FascinatingStateData, _TimeoutInterval = interval_milliseconds () }. %% This gets called automatically as a result of our handlers %% including the optional _TimeoutInterval value in the returned %% Result handle_info(timeout, StateData)-> {noreply, _State = do_some_work(StateData), _TimeoutInterval = interval_milliseconds () }.
Это работает, но это чрезвычайно хрупкое: если я хочу научить свой сервер новому сообщению, когда я пишу какую-либо новую функцию обработчика, я должен помнить о включении дополнительного интервала тайм-аута в его возвращаемое значение. То есть, скажем, если я обрабатываю синхронный вызов, мне нужно сделать это:
%% Someone wants to know our state; tell them handle_call(query_state_data, _From, StateData)-> {reply, StateData, _NewStateData = whatever (), interval_milliseconds ()};
вместо
%% Someone wants to know our state; tell them handle_call(query_state_data, _From, StateData)-> {reply, StateData, _NewStateData = whatever ()};
Как вы могли догадаться, я совершил эту ошибку несколько раз. Это неприятно, потому что, как только код обрабатывает это сообщение query_state_data, таймауты больше не генерируются, и весь сервер останавливается. (Я могу "дефибриллить" его вручную, получив оболочку на машине и отправив сообщение "тайм-аут" вручную, но... eww.)
Теперь я мог бы попытаться запомнить, чтобы всегда указывать этот необязательный параметр Timeout в моем значении Result. Но это не масштабируется: я когда-нибудь забуду, и снова буду смотреть на эту ошибку. Итак: какой лучший способ?
Я не думаю, что хочу написать фактический цикл, который работает вечно, и большую часть времени проводит спать; что противоречит духу ОТР.