io.grpc.Status vs com.google.rpc.Status

Hello!

It seems that LedgerAPI status messages and error messages can be handled in different ways depending on the library you use. My understanding is that the LedgerApi is built on gRPC, which is why I initially thought it would be more appropriate to use io.grpc.Status over com.google.rpc.Status, but it seems that com.google.rpc.Status is the native status type returned by the CompletionService.

  • CommandClient:
    • using submit with a blockingGet:
      • returns Empty on success
      • throws Throwable on failure
        • → can be converted to io.grpc.Status using io.grpc.fromThrowable(throwable)
        • → can be converted to com.google.rpc.Status using io.grpc.protobuf.StatusProto.fromThrowable(t)
    • using submit with an Observer:
      • onSuccess: returns Empty
      • onError: returns Throwabl e
        • → can be converted to io.grpc.Status using io.grpc.fromThrowable(throwable)
        • → can be converted to com.google.rpc.Status using io.grpc.protobuf.StatusProto.fromThrowable(t)
  • CommandSubmissionClient:
    • using submit with an Observer:
      • returns Empty on success
      • throws Throwable on failure
        • → can be converted to io.grpc.Status using io.grpc.fromThrowable(throwable)
        • → can be converted to com.google.rpc.Status using io.grpc.protobuf.StatusProto.fromThrowable(t)
  • CommandCompletionClient:
    • subscribed to completionStream with an Observer:
      • returns com.google.rpc.Status , which is contained in the CompletionStreamResponse
        • com.google.rpc.Status can be converted to io.grpc.Status by using getCode() and getMessage() then building io.grpc.Status.fromCodeValue().withDescription()
        • io.grpc.Status can be converted back to com.google.rpc.Status using com.google.rpc.Status.newBuilder().setCode().setMessage().build()

Questions:

  • Will using either of the libraries result in different description messages?
  • Is there a recommended approach which should be used?

We were previously using io.grpc.Status and had to do conversion to com.google.rpc.Status.

Thanks!
-Zoraiz

1 Like

Please note that the two Status classes cover different errors.

io.grpc.Status represents the success or failure of a call at a service level: a failure stems from an invalid argument, hitting an overloaded endpoint, and so on.

In the specific context of the command completion service, com.google.rpc.Status is the code generated for the Protobuf message that describes whether a command was executed successfully or not, and for what reason.

To make a specific example, you can make a call to the completion service that returns successfully (io.grpc.Status) and get a stream of completed commands, which can either have succeeded or failed (com.google.rpc.Status).

I would not try to convert between those two classes but use each at the relevant layer to address failures: you can for example have a retry strategy for calls that fail because of back-pressure on the Ledger API (io.grpc.Status) and a separate one to retry to issue specific commands that may have failed (com.google.rpc.Status).

4 Likes

Hi Stefano,

Thanks for the response! I just have a few questions that stem from your response.

Q1 . You mention that com.google.rpc.Status is used in the specific context of the Command Completion Service stream of completed commands. Would it be safe to imply that in every other context, we should be using io.grpc.Status?

Q2 . Having done some toying with the Command Service and the Command Completion Service, I found that having submitted a request using the Command Service, one could expect a response from the Command Completion Service if they were subscribed. This validated my understanding that the Command Service is a wrapper of the Command Submission Service and the Command Completion Service. With this in mind, if a transaction was submitted to the Command Service and failed, for example due to an assertion failure during execution, would we expect the same gRPC Error Code and Error Message in the Command Completion Service? This would be unusual considering I would handle an error from the Command Service using io.grpc.Status, whereas I would be using com.google.rpc.Status for the Command Completion Response. Are we guaranteed to have the same error description/message?

Q3. More on the topic of Command Service as a wrapper of the Command Submission Service and Command Completion Service. Based on the Command Service documentation: daml/command_service.proto at cda93db944afe55d987ba8b7d5326e256ae359cf · digital-asset/daml · GitHub , we see that there is a RESOURCE_EXHAUSTED error return if the number of in-flight commands reaches a maximum, and we have a limit set, which is also confirmed by Robert in When is RESOURCE_EXHAUSTED returned by the command submission/completion services? - #2 by Robert_Autenrieth . From our own research using Daml on VMWare Blockchain (VMBC), we have identified two other scenarios where RESOURCE_EXHAUSTED occurs: backpressure on client nodes, backpressure on replicas. Would the ‘in-flight’ commands issue imply there is a third scenario under which RESOURCE_EXHAUSTED might occur and is this exclusive to the Command Service?

Thank you!

Zoraiz

1 Like

For clarity: com.google.rpc.Status is used in the context of the command completion service to model an answer in the response. io.grpc.Status is not part of a response, it represents the status of the service call. I hope this clarifies.

2 Likes

In the case of the command service, a failed command will be wrapped in a failed service call, so you can expect that. The error message should be the same as the one you would see if you received the command status on the completion service.

2 Likes

Yes, in-flight means that the command has been submitted but an answer has not yet been received on the command completion service, so it only applies to the command service.

2 Likes