Узел gRPC с подробностью машинописного текста

#node.js #typescript #protocol-buffers #grpc

Вопрос:

Я пытаюсь настроить сервер gRPC узла в Typescript, и у меня все работает, но многословие обработки запросов/ответов оставляет у меня плохое предчувствие. Я следовал примеру https://github.com/blokur/grpc-ts-demo похоже, именно так устроено множество примеров проектов.

Проблема возникает при обработке запроса или ответа, и созданные заглушки средства создания кода ( grpc_tools_node_protoc ) требуют, чтобы вы обрабатывали запросы и ответы подобным образом:

   async getAllDogs(
    call: grpc.ServerWritableStream<Empty, DogEntity>,
  ): Promise<void> {
    const dogs = await dogService.repo.findAll();

    dogs
      .map((dogObj): DogEntity => {
        const dogEntity = new DogEntity();
        dogEntity.setBreed(dogObj.breed);
        dogEntity.setId(dogObj.id);
        dogEntity.setGoodBoyOrGirl(dogObj.goodBoyOrGirl);

        return dogEntity;
      })
      .forEach((dog) => {
        call.write(dog);
      });

    call.end();
  }
 

Тип, для которого создается DogEntity grpc_tools_node_protoc , является:

 export class DogEntity extends jspb.Message { 
    getId(): number;
    setId(value: number): DogEntity;
    getBreed(): string;
    setBreed(value: string): DogEntity;
    getGoodBoyOrGirl(): boolean;
    setGoodBoyOrGirl(value: boolean): DogEntity;

    serializeBinary(): Uint8Array;
    toObject(includeInstance?: boolean): DogEntity.AsObject;
    static toObject(includeInstance: boolean, msg: DogEntity): DogEntity.AsObject;
    static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
    static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
    static serializeBinaryToWriter(message: DogEntity, writer: jspb.BinaryWriter): void;
    static deserializeBinary(bytes: Uint8Array): DogEntity;
    static deserializeBinaryFromReader(message: DogEntity, reader: jspb.BinaryReader): DogEntity;
}

export namespace DogEntity {
    export type AsObject = {
        id: number,
        breed: string,
        goodBoyOrGirl: boolean,
    }
}
 

Поэтому, если в сообщении есть несколько полей или если вам нужно написать несколько обработчиков RPC, это может стать довольно подробным для построения ответов (и запросов на стороне клиента).

Мне интересно, реализовал ли кто-нибудь это таким образом, чтобы обеспечить уровень абстракции, позволяющий сократить объем кода, необходимого для выполнения чего-то вроде настройки конечных точек RPC типа CRUD.

Ответ №1:

На самом деле я нашел альтернативу для генерации кода-заглушки: https://github.com/stephenh/ts-proto

Эта библиотека позволяет создавать более гибкие типы, хотя для ее запуска требуется protoc непосредственное выполнение. Главное преимущество для меня в двух словах заключается в том, что теперь ответы можно создавать следующим образом:

   async getAllDogs(
    call: grpc.ServerWritableStream<Empty, DogEntity>,
  ): Promise<void> {
    const dogs = await dogService.repo.findAll();

    dogs.forEach((dog) => {
      call.write(DogEntity.fromJSON(dog));
    });

    call.end();
  }