LoginSignup
2
0

More than 3 years have passed since last update.

Nest.jsのgRPCで複数ファイル(パッケージ)に分割されたprotoファイルを読み込む

Posted at

About

Nest.jsのgRPC Microserviceにおいて、複数のファイルやパッケージに分割されたprotoファイルを読み込む方法が公式チュートリアルでは分からなかったので、調べた結果を残しておきます。

前提

protoファイルとパッケージを次のような構成とします。

.
├── animal
│   ├── animal.proto
│   └── cat
│       └── cat.proto
└── human
    └── human.proto
animal/animal.proto
package animal;

service AnimalService {
  rpc GetAnimal (GetAnimalRequest) returns (GetAnimalResponse) {}
}
animal/cat/cat.proto
package animal.cat;

service CatService {
  rpc GetCat (GetCatRequest) returns (GetCatResponse) {}
}
animal/human/human.proto
package human;

service HumanService {
  rpc GetHuman (GetHumanRequest) returns (GetHumanResponse) {}
}

まとめると、パッケージも含めたサービスのリストは下記のようになります。

animal.AnimalService
animal.dog.DogService
human.HumanService

複数ファイル

まず、main.tsで指定するGrpcOptionsは次のようになります。

src/main.ts
  const app = await NestFactory.createMicroservice<GrpcOptions>(AppModule, {
    transport: Transport.GRPC,
    options: {
      url: '0.0.0.0:6565',
      // ポイント: パッケージを配列で指定
      // ポイント: サブパッケージ(animal.dog)を含めると重複になるので含めない
      package: ['animal', 'human'],
      // ポイント: protoファイルを配列で指定
      protoPath: [
        join(__dirname, 'proto/animal/animal.proto'),
        join(__dirname, 'proto/animal/dog/dog.proto'),
        join(__dirname, 'proto/human/human.proto')
      ],
    }
  });
  app.listenAsync();

次に、Controller側ですが、最上位パッケージ直下のサービスなのか、サブパッケージのサービスなのかで、@GrpcMethodデコレーターのサービス名の指定方法が変わってきます。

最上位パッケージ直下のサービス
  @GrpcMethod('AnimalService', 'GetAnimal')
  getAnimal(req: IGetAnimalRequest): Promise<IGetAnimalResponse> {
    ...
  }

  @GrpcMethod('HumanService', 'GetAnimal')
  getAnimal(req: IGetHumanRequest): Promise<IGetHumanResponse> {
    ...
  }
サブパッケージのサービス
  // dog.が必要
  @GrpcMethod('dog.DogService', 'GetDog')
  getAnimal(req: IGetDogRequest): Promise<IGetDoglResponse> {
    ...
  }

参考: 直面したエラー

ケース1: サブパッケージを重複読み込み

GrpcOptionsのパッケージしていにサブパッケージも含めてしまうと、次のようなエラーが発生してしまいました。

Method handler for /animal.dog.DogService/GetDog already provided

src/main.ts
  const app = await NestFactory.createMicroservice<GrpcOptions>(AppModule, {
    transport: Transport.GRPC,
    options: {
      url: '0.0.0.0:6565',
      package: ['animal', 'animal.dog', 'human'],
      protoPath: [
        join(__dirname, 'proto/animal/animal.proto'),
        join(__dirname, 'proto/animal/dog/dog.proto'),
        join(__dirname, 'proto/human/human.proto')
      ],
    }
  });
  app.listenAsync();

ケース2: サブパッケージのサービス名の名前解決が不正

サブパッケージのサービス名の名前解決

Method handler GetDog for /animal.dog.DogService/GetDog expected but not provided

  @GrpcMethod('DogService', 'GetDog')
  getAnimal(req: IGetDogRequest): Promise<IGetDoglResponse> {
    ...
  }
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0