我有一个进程需要每十五秒做一些工作。我目前是这样做的:
-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消息,超时就不会再生成,整个服务器就会停止运行。(我可以通过在机器上获取shell并手动发送“timeout”消息来进行手动“除颤”,但是…呃。)
现在,我可以尝试记住始终在我的Result值中指定可选的Timeout参数。 但是这样做无法扩展:总有一天我会忘记,并再次面对这个错误。那么:有更好的方法吗?
我认为我不想编写实际上永远运行并花费大部分时间睡眠的循环;那似乎与OTP的精神相悖。