Skip to content

Instantly share code, notes, and snippets.

@IanVaughan
Created August 15, 2018 10:23
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 IanVaughan/e93add747e01d2c2f4594909a57ca23d to your computer and use it in GitHub Desktop.
Save IanVaughan/e93add747e01d2c2f4594909a57ca23d to your computer and use it in GitHub Desktop.
elixir nested timeout
defmodule CallsProcess do
use GenServer
def start_link(state) do
GenServer.start_link(__MODULE__, state, name: __MODULE__)
end
def init(state), do: {:ok, state}
def handle_call(:test, _from, %{call_timeout: call_timeout} = state) do
GenServer.call(ProcessThatTimesout, :long_call, call_timeout)
{:reply, :done, state}
end
end
defmodule ProcessThatTimesout do
use GenServer
def start_link(opts) do
GenServer.start_link(__MODULE__, opts, name: __MODULE__)
end
def init(opts), do: {:ok, opts}
def handle_call(:long_call, _from, %{sleep_for: sleep_for} = state) do
:timer.sleep(sleep_for)
{:reply, :done, state}
end
end
defmodule Runner do
@doc """
Works correctly
## Example
iex> Runner.run1
:done
"""
def run1 do
ProcessThatTimesout.start_link(%{sleep_for: 1000})
GenServer.call(ProcessThatTimesout, :long_call, 2000)
end
@doc """
Shows how a simple timeput error propagates
## Example
iex> Runner.run2
** (exit) exited in: GenServer.call(ProcessThatTimesout, :long_call, 1000)
** (EXIT) time out
(elixir) lib/gen_server.ex:924: GenServer.call/3
"""
def run2 do
ProcessThatTimesout.start_link(%{sleep_for: 2000})
GenServer.call(ProcessThatTimesout, :long_call, 1000)
end
@doc """
Shows how a nested timeout crashes calling process
## Example
iex(1)> self()
#PID<0.103.0>
iex(2)> Runner.run3
** (EXIT from #PID<0.103.0>) shell process exited with reason: exited in: GenServer.call(ProcessThatTimesout, :long_call, 1000)
** (EXIT) time out
Interactive Elixir (1.7.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)>
22:53:41.959 [error] GenServer CallsProcess terminating
** (stop) exited in: GenServer.call(ProcessThatTimesout, :long_call, 1000)
** (EXIT) time out
(elixir) lib/gen_server.ex:924: GenServer.call/3
play3.exs:11: CallsProcess.handle_call/3
(stdlib) gen_server.erl:615: :gen_server.try_handle_call/4
(stdlib) gen_server.erl:647: :gen_server.handle_msg/5
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Last message: :test
State: %{call_timeout: 1000}
self()
#PID<0.108.0>
"""
def run3 do
ProcessThatTimesout.start_link(%{sleep_for: 2000})
CallsProcess.start_link(%{call_timeout: 1000})
GenServer.call(CallsProcess, :test, 3000)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment