【发布时间】:2010-10-20 15:31:24
【问题描述】:
我有一个需要每十五秒做一次工作的进程。我目前正在这样做:
-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。)
现在,我可以尝试记住始终在我的 Result 值中指定可选的 Timeout 参数。但这不成比例:总有一天我会忘记,并且会再次盯着这个错误。那么:有什么更好的方法?
我不认为我想编写一个永远运行并且大部分时间都在睡觉的实际循环;这似乎与 OTP 的精神背道而驰。
【问题讨论】:
标签: erlang erlang-otp