From 8d8e42bd8d402e4292d07ddf2249d220a41aebe6 Mon Sep 17 00:00:00 2001 From: Rishab Jaggi Date: Fri, 10 Sep 2021 15:19:41 -0400 Subject: [PATCH] Add details to grpc error status struct --- lib/grpc/error.ex | 22 +++++++++++++++------- test/grpc/integration/codec_test.exs | 3 ++- test/grpc/integration/server_test.exs | 13 +++++++++---- test/grpc/integration/stub_test.exs | 3 ++- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/lib/grpc/error.ex b/lib/grpc/error.ex index c6aff4dc..bf5cb7f5 100644 --- a/lib/grpc/error.ex +++ b/lib/grpc/error.ex @@ -5,17 +5,18 @@ defmodule GRPC.RPCError do # server side raise GRPC.RPCError, status: :unknown # preferred raise GRPC.RPCError, status: GRPC.Status.unknown, message: "error message" + raise GRPC.RPCError, status: GRPC.Status.unknown, details: [Google.Rpc.LocalizedMessage.new!(locale: “en-US”, message: “User friendly string”)] # client side {:error, error} = Your.Stub.unary_call(channel, request) """ - defexception [:status, :message] - @type t :: %__MODULE__{status: GRPC.Status.t(), message: String.t()} + defexception [:status, :message, :details] + @type t :: %__MODULE__{status: GRPC.Status.t(), message: String.t(), details: [any()]} alias GRPC.Status - @spec exception(Status.t(), String.t()) :: t + @spec exception(Status.t(), String.t(), [any()]) :: t def new(status) when is_atom(status) do exception(status: status) end @@ -47,12 +48,19 @@ defmodule GRPC.RPCError do parse_args(t, acc) end - def exception(status, message) when is_atom(status) do - %GRPC.RPCError{status: apply(GRPC.Status, status, []), message: message} + defp parse_args([{:details, details} | t], acc) do + acc = %{acc | details: details} + parse_args(t, acc) + end + + def exception(status, message, details \\ []) + + def exception(status, message, details) when is_atom(status) do + %GRPC.RPCError{status: apply(GRPC.Status, status, []), message: message, details: details} end - def exception(status, message) when is_integer(status) do - %GRPC.RPCError{status: status, message: message} + def exception(status, message, details) when is_integer(status) do + %GRPC.RPCError{status: status, message: message, details: details} end defp status_message(1), do: "The operation was cancelled (typically by the caller)" diff --git a/test/grpc/integration/codec_test.exs b/test/grpc/integration/codec_test.exs index ef28b96a..65d35ca8 100644 --- a/test/grpc/integration/codec_test.exs +++ b/test/grpc/integration/codec_test.exs @@ -49,7 +49,8 @@ defmodule GRPC.Integration.CodecTest do assert %GRPC.RPCError{ status: GRPC.Status.unimplemented(), - message: "No codec registered for content-type application/grpc+not-registered" + message: "No codec registered for content-type application/grpc+not-registered", + details: [] } == reply end) end diff --git a/test/grpc/integration/server_test.exs b/test/grpc/integration/server_test.exs index 3960bf10..a1d6e61d 100644 --- a/test/grpc/integration/server_test.exs +++ b/test/grpc/integration/server_test.exs @@ -109,7 +109,8 @@ defmodule GRPC.Integration.ServerTest do assert %GRPC.RPCError{ status: GRPC.Status.unauthenticated(), - message: "Please authenticate" + message: "Please authenticate", + details: [] } == reply end) end @@ -120,7 +121,11 @@ defmodule GRPC.Integration.ServerTest do req = Helloworld.HelloRequest.new(name: "unknown error") assert {:error, - %GRPC.RPCError{message: "Internal Server Error", status: GRPC.Status.unknown()}} == + %GRPC.RPCError{ + message: "Internal Server Error", + status: GRPC.Status.unknown(), + details: [] + }} == channel |> Helloworld.Greeter.Stub.say_hello(req) end) end @@ -129,7 +134,7 @@ defmodule GRPC.Integration.ServerTest do run_server([FeatureErrorServer], fn port -> {:ok, channel} = GRPC.Stub.connect("localhost:#{port}") rect = Routeguide.Rectangle.new() - error = %GRPC.RPCError{message: "Please authenticate", status: 16} + error = %GRPC.RPCError{message: "Please authenticate", status: 16, details: []} assert {:error, ^error} = channel |> Routeguide.RouteGuide.Stub.list_features(rect) end) end @@ -148,7 +153,7 @@ defmodule GRPC.Integration.ServerTest do run_server([TimeoutServer], fn port -> {:ok, channel} = GRPC.Stub.connect("localhost:#{port}") rect = Routeguide.Rectangle.new() - error = %GRPC.RPCError{message: "Deadline expired", status: 4} + error = %GRPC.RPCError{message: "Deadline expired", status: 4, details: []} assert {:error, ^error} = channel |> Routeguide.RouteGuide.Stub.list_features(rect, timeout: 500) diff --git a/test/grpc/integration/stub_test.exs b/test/grpc/integration/stub_test.exs index 7a256429..c9f3eb78 100644 --- a/test/grpc/integration/stub_test.exs +++ b/test/grpc/integration/stub_test.exs @@ -74,7 +74,8 @@ defmodule GRPC.Integration.StubTest do assert {:error, %GRPC.RPCError{ message: "Deadline expired", - status: GRPC.Status.deadline_exceeded() + status: GRPC.Status.deadline_exceeded(), + details: [] }} == channel |> Helloworld.Greeter.Stub.say_hello(req, timeout: 500) end) end