我有一个过程需要每十五秒做一些工作。目前,我正在做这样的:在Erlang定期做某些事情的最佳方式是什么?
-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并手动发送“超时”消息来手动“去纤颤”它,但是...... eww。)
现在,我可以尝试记住总是指定可选的Timeout参数在我的结果值。但是这并没有规模:有一天我会忘记,并会再次盯着这个bug。所以:什么是更好的方法?
我不认为我想写一个永久运行的实际循环,并且大部分时间都在睡觉;这似乎与OTP的精神相反。
这不是最好的解决办法:http://erlang.org/doc/efficiency_guide/commoncaveats.html#id60206 – mspanc 2017-09-17 11:59:39