Created
August 15, 2018 10:23
-
-
Save IanVaughan/e93add747e01d2c2f4594909a57ca23d to your computer and use it in GitHub Desktop.
elixir nested timeout
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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