From 998a30fea29a950b9f4e71432d91000379f9e48c Mon Sep 17 00:00:00 2001 From: cabol Date: Wed, 27 Oct 2021 14:06:34 +0200 Subject: [PATCH] [#140] Handle `:erpc` exception reason `{:erpc, reason}` --- .github/workflows/ci.yml | 4 ++-- lib/nebulex/exceptions.ex | 26 ++++++++++++++++++++++ lib/nebulex/rpc.ex | 3 +++ test/nebulex/adapters/partitioned_test.exs | 11 +++++++++ test/support/test_cache.ex | 7 ++++-- 5 files changed, 47 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ea3a9ac7..8c099bba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -88,9 +88,9 @@ jobs: uses: actions/cache@v1 with: path: priv/plts - key: '${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-plt-v3' + key: '${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-plt-v4' restore-keys: | - ${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-plt-v3 + ${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-plt-v4 - name: Run static analysis checks run: | diff --git a/lib/nebulex/exceptions.ex b/lib/nebulex/exceptions.ex index 8a854684..c756bf07 100644 --- a/lib/nebulex/exceptions.ex +++ b/lib/nebulex/exceptions.ex @@ -73,3 +73,29 @@ defmodule Nebulex.RPCMultiCallError do %__MODULE__{message: message} end end + +defmodule Nebulex.RPCError do + @moduledoc """ + Raised at runtime when a RPC error occurs. + """ + + @type t :: %__MODULE__{reason: atom} + + defexception [:reason] + + @impl true + def message(%__MODULE__{reason: reason}) do + format_reason(reason) + end + + # :erpc.call/5 doesn't format error messages. + defp format_reason({:erpc, _} = reason) do + """ + The RPC operation failed with reason: + + #{inspect(reason)} + + See :erpc.call/5 for more information about the error reasons. + """ + end +end diff --git a/lib/nebulex/rpc.ex b/lib/nebulex/rpc.ex index a73b4282..9b809cbc 100644 --- a/lib/nebulex/rpc.ex +++ b/lib/nebulex/rpc.ex @@ -144,6 +144,9 @@ defmodule Nebulex.RPC do {:exception, original, _} -> :erlang.raise(:error, original, __STACKTRACE__) + + other -> + reraise %Nebulex.RPCError{reason: other}, __STACKTRACE__ end end diff --git a/test/nebulex/adapters/partitioned_test.exs b/test/nebulex/adapters/partitioned_test.exs index 74f3680c..6b0d1ba2 100644 --- a/test/nebulex/adapters/partitioned_test.exs +++ b/test/nebulex/adapters/partitioned_test.exs @@ -179,6 +179,17 @@ defmodule Nebulex.Adapters.PartitionedTest do end end + test ":erpc error" do + assert Partitioned.put_all(for(x <- 1..100_000, do: {x, x}), timeout: 60_000) == :ok + assert Partitioned.get(1, timeout: 1000) == 1 + + msg = ~r"The RPC operation failed with reason:\n\n{:erpc, :timeout}" + + assert_raise Nebulex.RPCError, msg, fn -> + Partitioned.get(1, timeout: 0) + end + end + test "runtime error" do _ = Process.flag(:trap_exit, true) diff --git a/test/support/test_cache.ex b/test/support/test_cache.ex index a3b7956d..d0761c80 100644 --- a/test/support/test_cache.ex +++ b/test/support/test_cache.ex @@ -140,8 +140,11 @@ defmodule Nebulex.TestCache do @impl true def get(_, key, _) do - if is_integer(key), do: raise(ArgumentError, "Error") - :ok + if is_integer(key) do + raise ArgumentError, "Error" + else + :ok + end end @impl true