Skip to content

Instantly share code, notes, and snippets.

@minhajuddin
Created July 18, 2018 12:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save minhajuddin/663ae20cad246f1e3b1cf9493c7d8531 to your computer and use it in GitHub Desktop.
Save minhajuddin/663ae20cad246f1e3b1cf9493c7d8531 to your computer and use it in GitHub Desktop.
Rolling/Sliding timeouts for Elixir GenServers
defmodule SearchWorker do
use GenServer
@idle_timeout_ms 10 * 60 * 1000
@impl GenServer
def init(state) do
# send ourselves a message after 10 seconds and cleanup the proc tree when we get this
Process.send_after(self(), :idle_timeout, @idle_timeout_ms)
{:ok, state}
end
@impl GenServer
def handle_info(:idle_timeout, state) do
# do whatever you want to do to cleanup your process tree
shutdown_proc_tree(state)
{:noreply, state}
end
end
defmodule SearchWorker do
use GenServer
@idle_timeout_ms 10 * 60 * 1000
# client api
def touch(pid) do
GenServer.cast(pid, :touch)
end
@impl GenServer
def init(_opts) do
state = touch_idle_timer(%{})
{:ok, state}
end
@impl GenServer
def handle_cast(:touch, state) do
# cancel current timer
Process.cancel_timer(state.idle_timer)
# create a new timer
state = touch_idle_timer(state)
{:noreply, state}
end
def handle_info(:idle_timeout, state) do
# do whatever you want to do to cleanup your process tree
shutdown_proc_tree(state)
{:noreply, state}
end
defp touch_idle_timer(state) do
# send ourselves a message after 10 seconds and cleanup the proc tree when we get this
idle_timer = Process.send_after(self(), :idle_timeout, @idle_timeout_ms)
%{state | idle_timer: idle_timer}
end
end
defmodule SearchWorker do
use GenServer
@idle_timeout_ms 10 * 60 * 1000
# client api
def touch(pid) do
GenServer.cast(pid, :touch)
end
@impl GenServer
def init(_opts) do
state = touch_idle_timer(%{})
{:ok, state}
end
@impl GenServer
def handle_cast(:touch, state) do
state = touch_idle_timer(state)
{:noreply, state}
end
# we got our idle timeout let's clean it up
def handle_info({:idle_timeout, idle_timeout_ref}, %{idle_timeout_ref: idle_timeout_ref} = state) do
# do whatever you want to do to cleanup your process tree
shutdown_proc_tree(state)
{:noreply, state}
end
# we have an old timeout coming through, we should just ignore it
def handle_info({:idle_timeout, _ref}, state), do: {:noreply, state}
defp touch_idle_timer(state) do
idle_timeout_ref = make_ref()
# send ourselves a message after 10 seconds and cleanup the proc tree when we get this
idle_timer = Process.send_after(self(), {:idle_timeout, idle_timeout_ref}, @idle_timeout_ms)
%{state | idle_timer_ref: idle_timer_ref}
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment