[RAILS] Tipps zur Behandlung von gRPC-Fehlern in Ruby

Fassen Sie Tipps zur Fehlerbehandlung bei der Implementierung eines gRPC-Clients in Ruby zusammen

Annahme

tl;dr

Fangen Sie zuerst den Fehler ab

Die Antwort des gRPC-Aufrufs ist im Grunde einer der folgenden Codes.

enum Code {
  OK = 0;
  CANCELLED = 1;
  UNKNOWN = 2;
  INVALID_ARGUMENT = 3;
  DEADLINE_EXCEEDED = 4;
  NOT_FOUND = 5;
  ALREADY_EXISTS = 6;
  PERMISSION_DENIED = 7;
  UNAUTHENTICATED = 16;
  RESOURCE_EXHAUSTED = 8;
  FAILED_PRECONDITION = 9;
  ABORTED = 10;
  OUT_OF_RANGE = 11;
  UNIMPLEMENTED = 12;
  INTERNAL = 13;
  UNAVAILABLE = 14;
  DATA_LOSS = 15;
}

https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto Als Implementierung des gRPC-Servers denke ich, dass das normale System den Code OK (0) zurückgibt, und wenn ein Fehler auftritt, gibt es einen anderen Code (1 bis 15) als OK zurück.

Wenn ein Fehler zurückgegeben wird, scheint die grpc-Gem-Seite ohne Erlaubnis eine Ausnahme zu generieren, und wenn Sie nicht retten, wird das Programm dort gestoppt. Daher ist es notwendig, die Ausnahme mit Rettung wie folgt aufzunehmen.

    begin
      stub = HogeProto::HogeService::Stub.new("localhost:50051", :this_channel_is_insecure)
      res = stub.get_hoge
    rescue GRPC::BadStatus => ex
      res = "error"
    rescue ex
      res = "unexpected error"
    end

In der von gem definierten Fehlerklasse sind alle Klassen "BadStatus" Sie können sehen, dass es Klasse erbt.

In der Tat, wenn Sie sich den Vererbungsbaum der aufgetretenen Ausnahme ansehen

p ex.class.ancestors
# =>[GRPC::InvalidArgument, GRPC::BadStatus, GRPC::Core::StatusCodes, StandardError, Exception...

Grundsätzlich können Sie alle Ausnahmen mit GRPC :: BadStatus abfangen.

Wenn Sie detaillierter verarbeiten möchten, können Sie es in Einheiten wie "GRPC :: InvalidArgument" abholen.

Extrahieren Sie Informationen aus der erfassten Ausnahme

Lassen Sie uns die Informationen aus der erfassten Ausnahme extrahieren. Die BadStatus-Instanz hat vier Felder. https://github.com/grpc/grpc/blob/d48d39c4324f06a6da24bb4f67e8ef21166ba65b/src/ruby/lib/grpc/errors.rb#L49-L52

Erstellen Sie beispielsweise einen Fehler vom in Go implementierten gRPC-Server wie folgt und geben Sie ihn an ruby zurück.

server.go


  func (s *Server) set_name(name string) {
    st := status.New(codes.InvalidArgument, "invalid username")
    return nil, st.Err()
  }

client.rb


    begin
      stub = HogeProto::HogeService::Stub.new("localhost:50051", :this_channel_is_insecure)
      res = stub.set_name("hoge1")
    rescue GRPC::BadStatus => ex
      p ex.code # => 3
      p ex.message # => "3:invalid username"
      p ex.details # => "invalid username"
      res = "error"
    rescue ex
      res = "unexpected error"
    end

Ich habe die Meldungen Statuscode "3" und "ungültiger Benutzername" erhalten

Wenn Sie Fehlerdetails abrufen möchten, verwenden Sie die Methode to_rpc_status

Bis zu dem oben genannten wurden der Statuscode und die Fehlermeldung erhalten. Ich denke jedoch, dass Fehlerdetails häufig verwendet werden, um die Details des Fehlers zu übergeben. https://christina04.hatenablog.com/entry/grpc-error-details https://grpc.io/docs/guides/error/#richer-error-model

Wenn Sie detailliertere Informationen einschließlich Fehlerdetails wünschen, können Sie mithilfe der Methode to_rpc_status detailliertere Informationen erhalten. Die Implementierung von "to_rpc_status" ist wie folgt: Sie können in den Typ "Google :: Rpc :: Status" umwandeln und detaillierte Informationen, einschließlich Trailer-Metadaten, abrufen. https://github.com/grpc/grpc/blob/d48d39c4324f06a6da24bb4f67e8ef21166ba65b/src/ruby/lib/grpc/errors.rb#L63-L75

Ich habe dem vorherigen Implementierungsbeispiel Fehlerdetails hinzugefügt.

server.go


  func (s *Server) set_name(name string) {
    st := status.New(codes.InvalidArgument, "invalid username")

    //Erstellen und Festlegen von Informationen zu Fehlerdetails
    desc := "The username must only contain alphanumeric characters"
    v := &errdetails.BadRequest_FieldViolation{
		Field:       "username",
		Description: desc,
    }
    br := &errdetails.BadRequest{}
    br.FieldViolations = append(br.FieldViolations, v)
    st, _ = st.WithDetails(br)
    
    return nil, st.Err()
  }

client.rb


require 'google/rpc/error_details_pb'

    begin
      stub = HogeProto::HogeService::Stub.new("localhost:50051", :this_channel_is_insecure)
      res = stub.set_name("hoge1")
    rescue GRPC::BadStatus => ex
      p ex.class # => GRPC::InvalidArgument
      p ex.to_rpc_status.class # => Google::Rpc::Status
      p ex.to_rpc_status # => <Google::Rpc::Status: code: 3, message: "invalid username", details: [<Google::Protobuf::Any: type_url: "type.googleapis.com/google.rpc.BadRequest", value: "\nC\n\tusername\x126The username must only contain alphanumeric characters">]>

      ex.to_rpc_status.details.each do |detail|
        p detail.type_url # => "type.googleapis.com/google.rpc.BadRequest"
        p detail.unpack(Google::Rpc::BadRequest) # => <Google::Rpc::BadRequest: field_violations: [<Google::Rpc::BadRequest::FieldViolation: field: "username", description: "The username must only contain alphanumeric characters">]>
      end
      res = "error"
    rescue ex
      res = "unexpected error"
    end

Bemerkenswerte Details Details: [<Google :: Protobuf :: Any: type_url:" type.googleapis.com/google.rpc.BadRequest ", Wert:" \ nC \ n \ tusername2 \ x126Der Benutzername darf nur alphanumerisch sein Die Zeichen ">] Teil. Dies sind die Fehlerdetails, die als Trailer gesendet wurden, und es gibt einige Daten vom Typ "Google :: Protobuf :: Any" und Wertdaten. Sie können mehrere Fehlerdetails festlegen, die als Array zurückgegeben werden. Sie müssen also alle drehen, um sie abzurufen. "type_url" ist der Speicherort für die Typdefinition für Fehlerdetails. Wenn Sie standardmäßig den von Google bereitgestellten Typ verwenden, lautet dieser "type.googleapis.com/google.rpc.BadRequest". .. Natürlich können Sie auch Ihren eigenen definierten Typ als Fehlerdetails festlegen. In diesem Fall wird der in der Protodatei definierte Speicherort gespeichert.

Außerdem ist die zurückgegebene Instanz vom Typ "Google :: Protobuf :: Any". Wenn sie unverändert bleibt, können die Daten in einem serialisierten Zustand nicht ordnungsgemäß abgerufen werden. Daher wird die Entpackungsmethode verwendet. Durch Bestimmen des Typs mit type_url und Umwandeln in den Typ, den Sie mit unpack zurückgeben möchten, konnte ich endlich Fehlerdetails abrufen. Beachten Sie übrigens, dass Sie "google / rpc / error_details_pb" importieren müssen, um die Typdefinition von "Google :: Rpc :: BadRequest" anzuzeigen.

Impressionen

Das Abrufen der Fehlerdetails hat viel Zeit in Anspruch genommen. Der Beispielcode unter https://grpc.io/docs/languages/ruby/quickstart/ behandelt dies nicht im Detail, daher ist es etwas schmerzhaft, den Inhalt des Edelsteins einzeln durchgehen zu müssen.

Recommended Posts

Tipps zur Behandlung von gRPC-Fehlern in Ruby
Tipps zum Umgang mit Enum mit Thymeleaf
Tipps zum Umgang mit Pseudoelementen in Selen
Fehlerbehandlung mit Graphql-Ruby
[Ruby] Ausnahmebehandlung in Funktionen
Implementieren Sie den gRPC-Client in Ruby
Wichtige Punkte für die Einführung von gRPC in Java
[Ruby / Rails] Mechanismus zum erneuten Versuch eines Thread-Fehlers
Behandlung von Ruby-Ausnahmen
Tipps für java.nio.file.Path
[WIP] Ruby-Tipps
Ruby-Ausnahmebehandlung
Schwer in Rubin! ??
So implementieren Sie Paginierung in GraphQL (für Ruby)
Tipps zum Generieren von Dateien für Eclipse-Projekte mit Gradle
Problemumgehung für Bundler.require-Fehler beim Ausführen von Ruby mit crontab
Tipps zum Festlegen der anfänglichen Verzögerung für Poller in XML
Tipps zur guten Verwendung von Canvas mit Xcode
ActiveModel :: UnknownAttributeError: Unbekanntes Attribut'foreign_type 'für die Fehlerbehandlung von PaperTrail :: VersionAssociation
[Für Anfänger] ○○. △△ in Ruby (ActiveRecord-Methode, Instanzmethode, Datenerfassung)
So beheben Sie den SSL_connect-Fehler im PayPal Ruby SDK
Umgang mit Datum und Uhrzeit in Ruby. Verwenden Sie Datum und Uhrzeit richtig.
Informationen zu Ruby-Fehlermeldungen
Informationen zur Behandlung von Ruby-Ausnahmen
Abkürzung für Ruby-Methode
Ausgabedreieck in Ruby
Arten von Variablen in Ruby
Schneller Popcount in Ruby
Integer # pow wird empfohlen, um die Quadratmethode in Ruby wiederholt zu lösen
Ich habe mit Gem in Ruby nach einem Webframework gesucht
Tipps zur Verwendung von Salesforce SOAP und Bulk API in Java
Mikro-Benchmark für Gleitkommazahlen zur Potenz von ganzen Zahlen in Ruby
Behandlung von Zeilenanfang und Zeilenende in regulären Ausdrücken in Ruby