我有一個過程需要每十五秒做一些工作。目前,我正在做這樣的:在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