Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better error handling #170

Closed
praveenperera opened this issue Aug 17, 2020 · 9 comments · Fixed by #314
Closed

Better error handling #170

praveenperera opened this issue Aug 17, 2020 · 9 comments · Fixed by #314

Comments

@praveenperera
Copy link

I think the error handling good be improved a little bit. Instead of always returning the same RPCError struct we could pattern match on the status code and return different errors. Currently I'm doing it like below. If you like this approach I could do a PR:

defmodule Bossman.Job.Error do
  defmodule NotFound, do: defexception([:message])
  defmodule Unknown, do: defexception([:message])
  defmodule InvalidArgument, do: defexception([:message])

  def new(%GRPC.RPCError{message: message, status: status}) do
    status_to_error_struct(status, URI.decode(message))
  end

  defp status_to_error_struct(2, msg), do: %Unknown{message: msg}
  defp status_to_error_struct(3, msg), do: %InvalidArgument{message: msg}
  defp status_to_error_struct(5, msg), do: %NotFound{message: msg}
end
@polvalente
Copy link
Contributor

@praveenperera would you still like to contribute with this?

I think this approach is good and we can accompany it with a is_rpc_error guard so users can still match in a generic manner wherever needed.

@polvalente
Copy link
Contributor

Another possible solution is to just document the status atoms better

@hackvan
Copy link
Contributor

hackvan commented May 30, 2023

Another possible solution is to just document the status atoms better

Hi @polvalente,

Do you think its enough adding an ASCII table in the @moduledoc like this:

Error Status Status Message
0 :ok
1 :cancelled The operation was cancelled (typically by the caller)
2 :unknown Unknown error
3 :invalid_argument Client specified an invalid argument
4 :deadline_exceeded Deadline expired before operation could complete
5 :not_found Some requested entity (e.g., file or directory) was not found
6 :already_exists Some entity that we attempted to create (e.g., file or directory) already exists
7 :permission_denied The caller does not have permission to execute the specified operation
8 :resource_exhausted Some resource has been exhausted
9 :failed_precondition Operation was rejected because the system is not in a state required for the operation's execution
10 :aborted The operation was aborted
11 :out_of_range Operation was attempted past the valid range
12 :unimplemented Operation is not implemented or not supported/enabled in this service
13 :internal Internal errors
14 :unavailable The service is currently unavailable
15 :data_loss Unrecoverable data loss or corruption
16 :unauthenticated The request does not have valid authentication credentials for the operation

Would it be better to include it in the GRPC.Status module or in the GRPC.RPCError module?

@polvalente
Copy link
Contributor

@hackvan I think that's perfect. We can put that in GRPC.Status and add something like "See GRPC.Status for more details on possible statuses" in GRPC.Error

@polvalente
Copy link
Contributor

I think we could provide this macro in GRPC.RPCError together with the better documentation:

defmacro is_rpc_error(e, status) when is_struct(e, GRPC.RPCError) and e.status == status

Which would make it easier for users to pattern match on different error types without the hassle of dealing with many different kinds of structs

hackvan added a commit to hackvan/grpc that referenced this issue May 30, 2023
Adds a markdown table to detail each code status and its related message.

Closes elixir-grpc#170
@hackvan
Copy link
Contributor

hackvan commented May 30, 2023

@hackvan I think that's perfect. We can put that in GRPC.Status and add something like "See GRPC.Status for more details on possible statuses" in GRPC.Error

What do you think?
image

I think we could provide this macro in GRPC.RPCError together with the better documentation...

For this I don't get it what is the purpose or a case use for this macro 😅

@polvalente
Copy link
Contributor

That looks good, but I'd format it with a markdown table so ex doc renders it nicely.

The guard (I wrote defmacro but should have been defguard there) covers the use case mentioned in the issue body itself, where instead of having different structs for pattern matching, we can just use the guard for matching on different errors

@hackvan
Copy link
Contributor

hackvan commented May 30, 2023

That looks good, but I'd format it with a markdown table so ex doc renders it nicely.

Yeap, I did it that way:
image

image

The guard (I wrote defmacro but should have been defguard there) covers the use case mentioned in the issue body itself, where instead of having different structs for pattern matching, we can just use the guard for matching on different errors

Ok, I get it but in this case when the people need to use the defguard they would need to import the GRPC.RPCError module first, right?

@polvalente
Copy link
Contributor

Yes. Or require it. But that's a lot more manageable than aliasing N different structs

polvalente added a commit that referenced this issue Jun 8, 2023
* Docs: Improves the module docs for error statuses.

Adds a markdown table to detail each code status and its related message.

Closes #170

* Docs: Updates the reference link to see more details about GRPC status code

* Feat: Adds `is_rpc_error/2` guard clause to check if it's an RPCError struct

Fix and add some missing specs.

* Test: Add GRPC.Status and GRPC.RPCError unit tests

* Fix: Applies suggestions from the code review

* Adds examples about `is_rpc_error/2` clause in `GRPC.RPCError` module doc.
* Improves @SPEC with variable names.
*  Renames error_test.exs to rpc_error_test.exs file.
* Fixes markdown table syntax in `GRPC.Status` module doc.

* Fix: Use `mix format` on status_test.exs file

* Test: Refactor tests related to the expected status code and expected error message using a common factory function.

* update ex_doc and some formatting

* docs: improve docs for error handling

* test: improve testing

* dialyzer

---------

Co-authored-by: Paulo Valente <16843419+polvalente@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants