Home > Enterprise >  How to organize proto file to re-use message if possible?
How to organize proto file to re-use message if possible?

Time:02-18

I recently started working with protobuf in my golang project. I created below simple protobuf file. I have three different endpoints.

  • GetLink takes CustomerRequest as an input parameter and returns back CustomerResponse
  • GetBulkLinks takes BulkCustomerRequest as an input parameter and returns back BulkCustomerResponse
  • StreaLinks takes StreamRequest as an input parameter and returns back CustomerResponse

I am wondering if there is any way we can improve below proto file because CustomerRequest and BulkCustomerRequest has mostly everything in common except resources field so there is a duplication. And same goes with StreamRequest input parameter as it only takes clientId as the input parameter. Is there anything in protocol buffer which can reuse stuff from another message type?

Is there any better or efficient way to organize below proto file which reuses message accordingly?

syntax = "proto3";

option go_package = "github.com/david/customerclient/gen/go/data/v1";

package data.v1;

service CustomerService {
  rpc GetLink(CustomerRequest) returns (CustomerResponse) {};
  rpc GetBulkLinks(BulkCustomerRequest) returns (BulkCustomerResponse) {};
  rpc StreaLinks(StreamRequest) returns (CustomerResponse) {};
}

message CustomerRequest {
  int32 clientId = 1;
  string resources = 2;
  bool isProcess = 3;
}

message BulkCustomerRequest {
  int32 clientId = 1;
  repeated string resources = 2;
  bool isProcess = 3;
}

message StreamRequest {
  int32 clientId = 1;
}

message CustomerResponse {
  string value = 1;
  string info = 2;
  string baseInfo = 3;
  string link = 4;
}

message BulkCustomerResponse {
  map<string, CustomerResponse> customerResponse = 1;
}

CodePudding user response:

Is there anything in protocol buffer which can reuse stuff from another message type?

Composition.

However keep in mind that request and response payloads may change over time. Even if it looks like they have something in common today, they may diverge tomorrow. After all they are used in different RPCs. Then excessive coupling achieves the opposite effect and becomes technical debt.

Since your schema has literally no more than three fields for each message, I would leave everything as is. Anyway, if you really must, you may consider the following:

  • Extract the GetLink and GetBulkLinks common fields in a separate message and compose with that:
message CustomerRequestParams {
  int32 clientId = 1;
  bool isProcess = 2;
}

message CustomerRequest {
  CustomerRequestParams params = 1;
  string resources = 2;
}

message BulkCustomerRequest {
  CustomerRequestParams params = 1;
  repeated string resources = 2;
}
  • StreamRequest looks just fine with repeating clientId. Arguably a stream is conceptually different from a unary RPC, so just keep them separated. And it's just one field.
  • Related