GenServer safe shutdown

Hi,

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

Is this a correct approach?
Thanks!

You can’t. Even after you have checked the size of the inbox, there might come in new messages before shutting down.

Is there any reason why you want it to shut down instead of having it wait for the next item to process?

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.

Then clean it up explicitely after you know that you wont create any further work items. 101 of resource handling…

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.

Thanks, it looks interesting. I found out more information about GenServer timeouts here: Is there a way to self terminate a genserver after no activity?