Dmitriy (r3code) wrote,
Dmitriy
r3code

Category:

GRPC: обработка ошибок на клиенте

Разрабатывая сервис на GO с GRPC встал вопрос при описании proto файлов "Нужно ли вносить описание ошибки приложения в ответ?". Изначально я так и сделал. Определил новый тип Error и добавил его первым полем во все ответы, получилось так:

message Error {
message Metadata {
string key = 1;
string value = 2
}
string code = 1; // код ошибки, константа
string message = 2; // сообщение об ошибке
string detail = 3; // дополнительные данные об ошибке, пояснения 
repeated Metadata meta = 4; // метаданные в виде ключ=значение
}
message ConfigStatusAnswer {
// Данные ошибки. Заполнено в случае ошибки выполнения запроса
Error error = 1;
// дата последнего изменения конфигурации
google.protobuf.Timestamp last_changed_time = 2;
// контрольная сумма конфигурации (опционально)
string checksum = 3;
}

Вроде бы логично. Но я решил все таки посмотреть, как это рекомендуют делать разработчики gRPC.
Оказалось они предлагают не вносить это информацию в каждый ответ, а вписывать ее в метаданные и оттуда клиент их должен достать. Меня интерисовало также как это будет выглядеть в коде на TypeScript, т.к. мы используем Improbable grpc-web для публикации API и он умеет работать с TypeScript. В нашем проекте один из клиентов это одностраничик (SPA) на Vuejs, похоже на это пример в статье "A TODO app using grpc-web and Vue.js (12.2018)"

Как же создавать ошибки на сервере (Go) и обрабатывать их на клиенте (TypeScript) тогда?

На сервере

1. Тип Status должен быть использован для сообщения об ошибках через gRPC, он встроен, имеет несколько основных полей и поле для дополнительных данных, куда можно положить например информацию о том какое поле содержит ошибку. Есть много заготовленных кодов ошибок и типов сообщений для детализации ошибок, их хватает для описания основных ошибок API.
Интересно, что в части примеров в proto-файлах ошибку указывают внутри сообщений-ответов явно, а в других нет и передают через метаданные заголовков запросов gRPC.
Онако в статье [2]  пишут, что "хороший"  gRPC должен передавать ошибку в метаданных ответа и исползовать коды ошибок gRPC. Это полезно тем, что реализация gRPC на клиенте гарантирует, что принятая ошибка имеет тип "Staus" и помтому в коде на Go можно всегда использовать метод staus.Convert, что позволит вам получать базовую инфомрацию об ошибке едионнобразно. В итоге я убрал описания ошибок из ответов, они создаются сервером и передаются GRPC в служебных заголовках.
2. Использовать руководство по описанию ошибок в gRPC от Google. Как лучше описывать ошибки, когда их локализовать.
3. Отдавать ошибки с дополнительными даннми, используя метод Status.WithDetails в
----
См. также:
[1] Пример создания ошибок gRPC в коде на Go в бибилиотеке GoGo-protobuf
[2] Статья "Лучшие практики для ошибок при работе с gRPC" (2018г.)
[3] Ощущения разработчиков после использования gRPC+TypeScript в проекте (2019г.)
[4] Предложения по улучшению процесса разработки API (Google)


Tags: golang, grpc, protobuf
Subscribe

Posts from This Journal “golang” Tag

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 0 comments