How can I easily schedule a ‘safe’ exit of a GenServer after x hours? How can I be sure that after receiving a shutdown message there are no other message which are waiting to be processed? So far I the following idea came to my mind:
def handle_info(:shutdown, state) do
{:message_queue_len, inbox_has_messages} = Process.info(self(), :message_queue_len)
if inbox_has_messages != 0 || Enum.count(state.items) > 0 do
Process.send_after(self(), :shutdown, @shutdown_time)
Logger.debug "[#{state.object_id}] Shutdown delayed"
{:noreply, state}
else
Logger.debug "[#{state.object_id}] Shutdown due to inactivity."
{:stop, :normal, state}
end
end
This process sits in memory and handles items for several hours but after this time I do not need it anymore, so I would like to have some kind of clean-up mechanism.
You can use the built-in “timeout” feature of GenServers.
Instead of returning
{:reply, reply, state}
return
{:reply, reply, state, 10000}
Where the 10000 is the timeout value in ms. If no messages arrive to the process after that period, you will received a :timeout message that you handle in handle_info/2. You can choose then to stop the process as usual in GenServers.
Now, I’m not sure about the semantics of the timeout and if the race condition you describe can be avoided.