]> Entropealabs - wampex_client.git/commitdiff
handle call errors
authorChristopher <chris@entropealabs.com>
Tue, 17 Mar 2020 21:12:27 +0000 (16:12 -0500)
committerChristopher <chris@entropealabs.com>
Tue, 17 Mar 2020 21:12:27 +0000 (16:12 -0500)
lib/roles/caller.ex
lib/roles/peer.ex
lib/router/session.ex
lib/wampex.ex
test/wampex_test.exs

index 254a5abd7cb95bda531ec832071961b3edc25b45..c662f19c69c64abc436a265d552f6cd3cb685ee5 100644 (file)
@@ -4,10 +4,12 @@ defmodule Wampex.Roles.Caller do
   """
 
   alias Wampex.Role
+  alias Wampex.Roles.Peer.Error
   @behaviour Role
 
   @call 48
   @cancel 49
+  @error 8
   @result 50
 
   defmodule Call do
@@ -45,6 +47,11 @@ defmodule Wampex.Roles.Caller do
     [@call, opts, p, al, akw]
   end
 
+  @spec call_error(Error.t()) :: Wampex.message()
+  def call_error(%Error{request_id: rid, error: er, details: dets, arg_l: al, arg_kw: akw}) do
+    [@error, @call, rid, dets, er, al, akw]
+  end
+
   @spec cancel(Cancel.t()) :: Wampex.message()
   def cancel(%Cancel{request_id: ri, options: opts}) do
     [@cancel, ri, opts]
index 8bb79111f21eafbdbd868f2e39bb1db2bbb896b2..329765e84d75bbb7a243de8c0ea08afaee6a6ece 100644 (file)
@@ -81,6 +81,20 @@ defmodule Wampex.Roles.Peer do
           }
   end
 
+  defmodule Error do
+    @moduledoc false
+    @enforce_keys [:error]
+    defstruct [:request_id, :error, :arg_l, :arg_kw, details: %{}]
+
+    @type t :: %__MODULE__{
+            request_id: integer() | nil,
+            error: String.t(),
+            arg_l: list() | nil,
+            arg_kw: map() | nil,
+            details: map()
+          }
+  end
+
   @impl true
   def add(roles), do: roles
 
@@ -159,7 +173,7 @@ defmodule Wampex.Roles.Peer do
   end
 
   @impl true
-  def handle([@error, type, id, _dets, error, arg_l, arg_kw]) do
-    {[{:next_event, :internal, :established}], id, {:error, type, error, arg_l, arg_kw}}
+  def handle([@error, type, id, dets, error, arg_l, arg_kw]) do
+    {[{:next_event, :internal, :established}], id, {:error, type, error, dets, arg_l, arg_kw}}
   end
 end
index 30bcc59fcfabb48b7c7e19dfdad92224567dea68..b4c7c6365e3b0a03c1c3535b21b19e5f9891543e 100644 (file)
@@ -9,8 +9,8 @@ defmodule Wampex.Router.Session do
   alias __MODULE__, as: Sess
   alias StatesLanguage, as: SL
   alias Wampex.Realm
-  alias Wampex.Roles.{Broker, Dealer, Peer}
-  alias Wampex.Roles.Peer.{Challenge, Welcome, Abort}
+  alias Wampex.Roles.{Broker, Caller, Dealer, Peer}
+  alias Wampex.Roles.Peer.{Abort, Challenge, Error, Welcome}
   alias Wampex.Router
   alias Wampex.Serializers.JSON
   alias Broker.{Subscribed, Published, Event}
@@ -430,48 +430,67 @@ defmodule Wampex.Router.Session do
             %Sess{
               db: db,
               proxy: proxy,
-              transport: _tt,
-              transport_pid: _t,
+              transport: tt,
+              transport_pid: t,
               realm: realm,
               request_id: ri,
               call: {:call, call_id, dets, proc, al, akw}
             } = data
         } = sl
       ) do
-    {_key, callees} = ClusterKV.get(db, realm, proc, 500)
-
-    {data, actions} =
-      case get_live_callee(proxy, callees) do
-        {id, {pid, node}} ->
-          req_id = get_request_id(ri)
+    data =
+      with {_key, callees} <- ClusterKV.get(db, realm, proc, 500),
+           {id, {pid, node}} <- get_live_callee(proxy, callees) do
+        req_id = get_request_id(ri)
 
-          send(
-            {proxy, node},
+        send(
+          {proxy, node},
+          {
             {
-              {
-                call_id,
-                %Invocation{
-                  request_id: req_id,
-                  registration_id: id,
-                  options: dets,
-                  arg_list: al,
-                  arg_kw: akw
-                },
-                {self(), Node.self()}
+              call_id,
+              %Invocation{
+                request_id: req_id,
+                registration_id: id,
+                options: dets,
+                arg_list: al,
+                arg_kw: akw
               },
-              pid
-            }
+              {self(), Node.self()}
+            },
+            pid
+          }
+        )
+
+        %SL{sl | data: %Sess{data | request_id: req_id}}
+      else
+        {:error, :no_live_callees} ->
+          send_to_peer(
+            Caller.call_error(%Error{
+              request_id: call_id,
+              error: "wamp.error.no_callees",
+              details: %{procedure: proc}
+            }),
+            tt,
+            t
           )
 
-          {%SL{sl | data: %Sess{data | request_id: req_id}},
-           [{:next_event, :internal, :transition}]}
+          sl
 
-        {:error, :no_live_callees} ->
-          {%SL{sl | data: %Sess{data | error: "wamp.error.no_callees_registered"}},
-           [{:next_event, :internal, :transition}, {:next_event, :internal, :error}]}
+        :not_found ->
+          send_to_peer(
+            Caller.call_error(%Error{
+              request_id: call_id,
+              error: "wamp.error.no_registration",
+              details: %{procedure: proc}
+            }),
+            tt,
+            t
+          )
+
+          sl
       end
 
-    {:ok, data, actions}
+    {:ok, data, [{:next_event, :internal, :transition}]}
   end
 
   @impl true
@@ -482,22 +501,16 @@ defmodule Wampex.Router.Session do
         %SL{data: %Sess{proxy: proxy, invocations: inv, yield: {:yield, id, dets, arg_l, arg_kw}}} =
           data
       ) do
-    Logger.info("Handling yield #{id} - #{inspect(arg_kw)}")
-
-    case Enum.find(inv, fn
-           {_, %Invocation{request_id: ^id}, _} -> true
-           _ -> false
-         end) do
-      {call_id, _, {pid, node}} ->
-        send(
-          {proxy, node},
-          {%Result{request_id: call_id, arg_list: arg_l, arg_kw: arg_kw, options: dets}, pid}
-        )
+    {call_id, _, {pid, node}} =
+      Enum.find(inv, fn
+        {_, %Invocation{request_id: ^id}, _} -> true
+        _ -> false
+      end)
 
-      nil ->
-        Logger.error("No invocation in #{inspect(inv)} for #{id} #{inspect(arg_kw)}")
-        :noop
-    end
+    send(
+      {proxy, node},
+      {%Result{request_id: call_id, arg_list: arg_l, arg_kw: arg_kw, options: dets}, pid}
+    )
 
     inv =
       Enum.filter(inv, fn
@@ -556,7 +569,6 @@ defmodule Wampex.Router.Session do
 
   @impl true
   def handle_info(%Result{} = e, _, %SL{data: %Sess{transport: tt, transport_pid: t}} = data) do
-    Logger.info("Handling Result #{inspect(e)}")
     send_to_peer(Dealer.result(e), tt, t)
     {:ok, data, []}
   end
index 7b0565e1b9bd3a879298dcb6b3487672e6ad69bb..bdf7f14e3e3edc218d41d52c87aef106ee0bab2b 100644 (file)
@@ -41,8 +41,8 @@ defmodule Wampex do
            arg_list :: arg_list(), arg_keyword :: arg_keyword()}
   @type error ::
           {:error, reason :: binary()}
-          | {:error, type :: integer(), error :: binary(), arg_list :: arg_list(),
-             arg_keyword :: arg_keyword()}
+          | {:error, type :: integer(), error :: binary(), details :: map(),
+             arg_list :: arg_list(), arg_keyword :: arg_keyword()}
   @type messages ::
           publish()
           | hello()
index c5b562e32706bce84873bc0b8d1b5d3eb5bf1c5e..881d88b8cf1c5197761f239de8fad356f1c0b110 100644 (file)
@@ -281,6 +281,24 @@ defmodule WampexTest do
     assert_receive {:EXIT, ^pid, :shutdown}, 1000
   end
 
+  @tag :client
+  test "caller receives error when calling unknown procedure" do
+    caller_name = TestCaller
+    Client.start_link(name: caller_name, session: @session)
+
+    assert {:error, 48, "wamp.error.no_registration", %{"procedure" => "this.should.not.exist"},
+            nil,
+            nil} =
+             Client.send_request(
+               caller_name,
+               Caller.call(%Call{
+                 procedure: "this.should.not.exist",
+                 arg_list: [1],
+                 arg_kw: %{color: "#FFFFFF"}
+               })
+             )
+  end
+
   @tag :client
   test "callee is invoked and responds and caller gets result" do
     callee_name = TestCalleeRespond