Skip to content

Instantly share code, notes, and snippets.

@IanVaughan
Last active September 25, 2022 19:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save IanVaughan/1b3f14b430bb8480e07e2d8c9d48d94d to your computer and use it in GitHub Desktop.
Save IanVaughan/1b3f14b430bb8480e07e2d8c9d48d94d to your computer and use it in GitHub Desktop.
elixir genserver timeouts
defmodule CallsProcessOnTimeout do
use GenServer
def start_link(opts) do
self() |> IO.inspect(label: "#{__MODULE__}.start_link")
GenServer.start_link(__MODULE__, opts, name: __MODULE__)
end
def init(opts) do
self() |> IO.inspect(label: "#{__MODULE__}.init returing :ok, pid")
{:ok, opts, 1000}
end
def handle_info(:timeout, %{timeout_for: timeout_for, call_timeout: call_timeout} = state) do
self() |> IO.inspect(label: "#{__MODULE__}.handle_info :timeout")
ProcessThatTimesout.long_call(%{call_timeout: call_timeout})
{:noreply, state, timeout_for}
end
end
defmodule ProcessThatTimesout do
use GenServer
def start_link(opts) do
self() |> IO.inspect(label: "#{__MODULE__}.start_link")
GenServer.start_link(__MODULE__, opts, name: __MODULE__)
end
def init(opts) do
self() |> IO.inspect(label: "#{__MODULE__}.init returing :ok, pid")
{:ok, opts}
end
def long_call(%{call_timeout: call_timeout}) do
self() |> IO.inspect(label: "#{__MODULE__}.long_call timeout:#{inspect call_timeout}")
GenServer.call(__MODULE__, :long_call, call_timeout)
end
def handle_call(:long_call, _from, %{sleep_for: sleep_for} = state) do
self() |> IO.inspect(label: "#{__MODULE__}.handle_info :long_call")
:timer.sleep(sleep_for)
{:reply, :done, state}
end
end
defmodule Runner do
@doc """
iex(1)> self()
#PID<0.114.0>
iex(2)> Runner.run1
Elixir.ProcessThatTimesout.start_link: #PID<0.114.0>
Elixir.ProcessThatTimesout.init returing :ok, pid: #PID<0.118.0>
Elixir.ProcessThatTimesout.long_call timeout:2000: #PID<0.114.0>
Elixir.ProcessThatTimesout.handle_info :long_call: #PID<0.118.0>
:done
iex(3)> self()
#PID<0.114.0>
"""
def run1 do
ProcessThatTimesout.start_link(%{sleep_for: 1000})
ProcessThatTimesout.long_call(%{call_timeout: 2000})
end
@doc """
iex(1)> self()
#PID<0.106.0>
iex(2)> Runner.run2
Elixir.ProcessThatTimesout.start_link: #PID<0.106.0>
Elixir.ProcessThatTimesout.init returing :ok, pid: #PID<0.111.0>
Elixir.ProcessThatTimesout.long_call timeout:1000: #PID<0.106.0>
Elixir.ProcessThatTimesout.handle_info :long_call: #PID<0.111.0>
** (exit) exited in: GenServer.call(ProcessThatTimesout, :long_call, 1000)
** (EXIT) time out
(elixir) lib/gen_server.ex:774: GenServer.call/3
iex(1)> self()
#PID<0.106.0>
"""
def run2 do
ProcessThatTimesout.start_link(%{sleep_for: 2000})
ProcessThatTimesout.long_call(%{call_timeout: 1000})
end
@doc """
iex(1)> Runner.run3
Elixir.ProcessThatTimesout.start_link: #PID<0.108.0>
Elixir.ProcessThatTimesout.init returing :ok, pid: #PID<0.110.0>
Elixir.CallsProcessOnTimeout.start_link: #PID<0.108.0>
Elixir.CallsProcessOnTimeout.init returing :ok, pid: #PID<0.111.0>
{:ok, #PID<0.111.0>}
Elixir.CallsProcessOnTimeout.handle_info :timeout: #PID<0.111.0>
Elixir.ProcessThatTimesout.long_call timeout:1000: #PID<0.111.0>
Elixir.ProcessThatTimesout.handle_info :long_call: #PID<0.110.0>
** (EXIT from #PID<0.108.0>) evaluator process exited with reason: exited in: GenServer.call(ProcessThatTimesout, :long_call, 1000)
** (EXIT) time out
Interactive Elixir (1.5.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)>
19:25:48.060 [error] GenServer CallsProcessOnTimeout terminating
** (stop) exited in: GenServer.call(ProcessThatTimesout, :long_call, 1000)
** (EXIT) time out
(elixir) lib/gen_server.ex:774: GenServer.call/3
play2.exs:17: CallsProcessOnTimeout.handle_info/2
(stdlib) gen_server.erl:601: :gen_server.try_dispatch/4
(stdlib) gen_server.erl:667: :gen_server.handle_msg/5
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Last message: :timeout
State: %{call_timeout: 1000, timeout_for: 1000}
nil
iex(2)> self()
#PID<0.113.0>
"""
def run3 do
ProcessThatTimesout.start_link(%{sleep_for: 2000})
CallsProcessOnTimeout.start_link(%{timeout_for: 1000, call_timeout: 1000})
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment