Страницы

воскресенье, 5 ноября 2017 г.

Handling errors in gRPC

Вчера прочитал один пост на тему обработки ошибок в gRPC. На мой взгляд передавать вместе с ошибкой стэк - это уже перебор: сообщение, статус, может быть какой-нибудь код, прочие дополнительные поля (например Retry-After), но не стэк. По-моему стэк должен быть залогирован там где произошла ошибка, после чего его миссия завершена. Кроме того я не согласен с автором на предмет того, каким образом передавать все эти дополнительные поля: идея передавать ошибку вместе с данными (или вместо данных) мне не нравится, думаю метаданные здесь подойдут лучше.

Для примера немного подредактируем тестовый проект на Node.js из предыдущего поста:

- server.js:
const grpc = require('grpc')
const path = require('path')
 
const root = path.join(__dirname, 'protos')
const proto = grpc.load({ root, file: 'test.proto' })
 
const server = new grpc.Server()
server.addService(proto.test.Greeter.service, {
  hello: (call, cb) => {
    console.log('req:', call.request)
    if (call.request.name === 'world') {
      const metadata = new grpc.Metadata()
      metadata.set('statusCode', String(400))
      const err = new Error('My Error')
      err.metadata = metadata
      return cb(err)
    }
    cb(null, `Hello, ${call.request.name}`)
  }
})
server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure())
server.start()

- client.js:
const grpc = require('grpc')
const path = require('path')
 
const root = path.join(__dirname, 'protos')
const proto = grpc.load({ root, file: 'test.proto' })
 
const client = new proto.test.Greeter('localhost:50051', grpc.credentials.createInsecure())
client.hello({ name: process.argv[2] || 'world' }, (err, res) => {
  if (err) return console.error(err)
  console.log('res:', res)
})



Ничто не мешает вытащить статус ошибки из метаданных:
- client.js:
const grpc = require('grpc')
const path = require('path')
 
const root = path.join(__dirname, 'protos')
const proto = grpc.load({ root, file: 'test.proto' })
 
const client = new proto.test.Greeter('localhost:50051', grpc.credentials.createInsecure())
client.hello({ name: process.argv[2] || 'world' }, (err, res) => {
  if (err) {
    err.status = Number(err.metadata.get('statusCode')[0])
    return console.error(err)
  }
  console.log('res:', res)
})


А как вы обрабытываете ошибки gRPC?