Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 2 additions & 12 deletions lib/xandra/cluster.ex
Original file line number Diff line number Diff line change
Expand Up @@ -434,12 +434,7 @@ defmodule Xandra.Cluster do
cluster,
options,
fn conn ->
try do
Xandra.execute(conn, batch, options_without_retry_strategy)
catch
:exit, {:noproc, _} ->
{:error, ConnectionError.new("execute", {:cluster, :pool_closed})}
end
Xandra.execute(conn, batch, options_without_retry_strategy)
end
)
end
Expand All @@ -463,12 +458,7 @@ defmodule Xandra.Cluster do
cluster,
options,
fn conn ->
try do
Xandra.execute(conn, query, params, options_without_retry_strategy)
catch
:exit, {:noproc, _} ->
{:error, ConnectionError.new("execute", {:cluster, :pool_closed})}
end
Xandra.execute(conn, query, params, options_without_retry_strategy)
end
)
end
Expand Down
10 changes: 8 additions & 2 deletions lib/xandra/connection.ex
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ defmodule Xandra.Connection do

telemetry_metadata = Keyword.fetch!(options, :telemetry_metadata)

case :gen_statem.call(conn_pid, {:checkout_state_for_next_request, req_alias}) do
case gen_statem_call_trapping_noproc(conn_pid, {:checkout_state_for_next_request, req_alias}) do
{:ok, checked_out_state() = state} ->
checked_out_state(
protocol_module: protocol_module,
Expand Down Expand Up @@ -159,7 +159,7 @@ defmodule Xandra.Connection do
conn_pid = GenServer.whereis(conn)
req_alias = Process.monitor(conn_pid, alias: :reply_demonitor)

case :gen_statem.call(conn_pid, {:checkout_state_for_next_request, req_alias}) do
case gen_statem_call_trapping_noproc(conn_pid, {:checkout_state_for_next_request, req_alias}) do
{:ok, checked_out_state() = checked_out_state} ->
checked_out_state(
transport: %Transport{} = transport,
Expand Down Expand Up @@ -226,6 +226,12 @@ defmodule Xandra.Connection do
end
end

defp gen_statem_call_trapping_noproc(pid, call) do
:gen_statem.call(pid, call)
catch
:exit, {:noproc, _} -> {:error, :no_connection_process}
end

defp hydrate_query(%Simple{} = simple, checked_out_state() = response, options) do
%Simple{
simple
Expand Down
4 changes: 4 additions & 0 deletions lib/xandra/connection_error.ex
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ defmodule Xandra.ConnectionError do
"connection dropped in the middle of a request"
end

defp format_reason(:no_connection_process) do
"the connection process doesn't exist"
end

defp format_reason({:connection_process_crashed, reason}) do
"connection process crashed before sending a response with reason: #{inspect(reason)}"
end
Expand Down
3 changes: 2 additions & 1 deletion test/integration/errors_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ defmodule ErrorsTest do
test "noproc errors are caught" do
{:ok, cluster} = start_supervised(Xandra.Cluster.PoolMock)

assert {:error, %ConnectionError{action: "execute", reason: {:cluster, :pool_closed}}} =
assert {:error,
%ConnectionError{action: "check out connection", reason: :no_connection_process}} =
Cluster.execute(cluster, "select * from system.peers")
end
end
Expand Down
24 changes: 24 additions & 0 deletions test/xandra_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,22 @@ defmodule XandraTest do
assert {:ok, prepared} = Xandra.prepare(conn, "SELECT * FROM system.local")
assert {:ok, %Xandra.Page{}} = Xandra.execute(conn, prepared, [])
end

test "returns an error when the Connection process doesn't exist" do
dead_pid = dead_pid()

assert {:error,
%ConnectionError{action: "check out connection", reason: :no_connection_process}} =
Xandra.prepare(dead_pid, "SELECT * FROM system.local")

refute_receive {:DOWN, _ref, :process, _pid, :noproc}, 5

assert {:error,
%ConnectionError{action: "check out connection", reason: :no_connection_process}} =
Xandra.execute(dead_pid, "SELECT * FROM system.local")

refute_receive {:DOWN, _ref, :process, _pid, :noproc}, 5
end
end

describe "failure handling" do
Expand Down Expand Up @@ -390,4 +406,12 @@ defmodule XandraTest do
send(pid, {ref, options})
Keyword.replace!(options, :nodes, original_start_options[:nodes])
end

defp dead_pid do
{pid, ref} = spawn_monitor(fn -> :ok end)

receive do
{:DOWN, ^ref, _, _, _} -> pid
end
end
end