Hello! I created the minimum code possible to explain my case:
defmodule DelayedReply do
use GenServer
def start_link(), do: GenServer.start_link(__MODULE__, [])
def my_call(pid), do: GenServer.call(pid, :call, 100)
@impl true
def init([]) do
{:ok, []}
end
@impl true
def handle_call(:call, caller, state) do
Process.send_after(self(), {:call, caller}, 500)
{:noreply, state}
end
@impl true
def handle_info({:call, caller}, state) do
{pid, _ref} = caller
send(pid, :custom_message)
GenServer.reply(caller, :ok)
{:noreply, state}
end
end
test "test" do
assert {:ok, server} = DelayedReply.start_link()
try do
DelayedReply.my_call(server)
catch
:exit, {:timeout, _} -> :ok
end
assert_receive :custom_message, 5000
# Never received the GenServer.reply message
assert_receive _msg, 5000
end
If the caller doesn’t die because there is a try/catch block; why the GenServer.reply
is not received?
A similar example with the same result:
defmodule SleepReply do
use GenServer
def start_link(), do: GenServer.start_link(__MODULE__, [])
def my_call(pid), do: GenServer.call(pid, :call, 100)
@impl true
def init([]) do
{:ok, []}
end
@impl true
def handle_call(:call, caller, state) do
Process.sleep(200)
{pid, _} = caller
send(pid, :custom_message)
{:reply, :ok, state}
end
end
test "test 2" do
assert {:ok, server} = SleepReply.start_link()
try do
SleepReply.my_call(server)
catch
:exit, {:timeout, _} -> :ok
end
assert_receive :custom_message, 1000
assert_receive _msg, 1000
end
How does the GenServer know that the call times out?
Thank you!