#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();
}