GRPC Service with Generic proto request data in GoLang - go

I have 3 protos as follow:
1 - record.proto
message Record {
int64 primaryKey = 1;
int64 createdAt = 2;
int64 updatedAt = 3;
}
2 - user.proto
import "record.proto";
message User {
Record record = 31;
string name = 32;
string email = 33;
string password = 34;
}
3 - permissions.proto
import "record.proto";
message Permissions{
Record record = 31;
string permission1= 32;
string permission2= 33;
}
Question1:
Is there a way to implement a grpc server and client in golang that takes specifically Record as request but entertains both later types. i.e User and Permissions.
Something like:
service DatabaseService {
rpc Create(Record) returns (Response);
}
So that I can send grpc client request as both follow:
Create(User) returns (Response);
Create(Permissions) returns (Response);

You can use oneof which allows the client to send either User or Permissions.
Refer https://developers.google.com/protocol-buffers/docs/proto3#oneof
message Request {
oneof request {
User user = 1;
Permissions permissions = 2;
}
}
So client can fill any of them in the request.
service DatabaseService {
rpc Create(Request) returns (Response);
}

Related

Parse nested (opaque, any-typed) Protobuf message

I have a message envelope:
import "google/protobuf/any.proto";
message Envelope {
string type = 1;
int32 version = 2;
string message_id = 5;
string timestamp = 6;
google.protobuf.Any message = 7;
}
Now, I happen to know that the message is another Protobuf value with the following type:
And a message defined as follows:
message Message {
int32 value = 1;
string name = 2;
}
Is it possible for me to do a one-shot parsing of this combined message? I am thinking that the problem with substituting Any with Message is the field numbering.
Any is just:
message Any {
string type_url = 1;
bytes value = 2;
}
where the value is just the regular payload content. If you know that the type is your Message, then you can use instead
message Envelope {
string type = 1;
int32 version = 2;
string message_id = 5;
string timestamp = 6;
FakeAny message = 7;
}
message FakeAny {
// don't even need to capture the type_url
Message value = 2;
}
message Message {
int32 value = 1;
string name = 2;
}
and it should deserialize directly.

Reusing Message in the same package in multiple files

Is there a way to reuse protobuf structs across multiple proto files?
in the client.proto file I have the following
message SingleOperation {
string command = 1;
}
message ClientBatch {
string unique_id = 1;
repeated SingleOperation requests = 2;
int64 sender = 3;
}
Then in network.proto file, I have the following
message MemPool {
int32 sender = 1;
string unique_id = 2;
SingleOperation op = 3;
}
In the network.proto file, I need to reuse the SingleOperation message.
However, I do not see an option to do this.
Does protobuff support some sort of packaging to support struct reuse?

How to define empty parameter for Protocol Buffers rpc method?

I have a method that I would like defined called FindAll which requires no parameters. ProtoC is complaining.
Expected type name.
This is for line:
rpc findAll () returns (BenchmarksList);
syntax = "proto3";
package helloWorldGRPC;
service HelloWorldGRPCService {
rpc findById (BenchmarksById) returns (Benchmarks);
rpc findAll () returns (BenchmarksList);
}
message BenchmarksById {
string id = 1;
}
message BenchmarksList {
repeated Benchmarks benchmarks = 1;
}
message Benchmarks {
string trans_id = 1;
string protocol = 2;
string database = 3;
string updated_at = 4;
string created_at = 5;
repeated Action actions = 6;
}
message Action {
string trans_id = 1;
int32 payload_length = 2;
string payload = 3;
string status = 4;
string updated_at = 5;
string created_at = 6;
}
The preferred way is to pass Empty - as tooling may recognize and optimize for that scenario. But in reality, there is nothing "special" about that type and any message - empty or otherwise - will suffice.

In a proto, how can I define a map as a custom option

In my proto file, I want to define a map as a custom option, tried a few things but none is working.
my metadata proto file:
syntax = "proto2";
import "google/protobuf/descriptor.proto";
package com.util;
option java_package = "com.util";
message MyMeta {
optional bool needValidation = 1;
map<string, string> fileMap = 2;
}
extend google.protobuf.FieldOptions {
optional MyMeta meta = 80412;
}
my proto file
syntax = "proto3";
package com.test;
import "util/meta.proto";
import "google/protobuf/timestamp.proto";
message MyMeta {
int32 id = 1 [(com.util.meta).needValidation = false, /*looking for a way to set a map (com.meta).tableOptions = {"t,raw_orders"}]*/;
}
Is this possible?
This works:
message MyMeta {
int32 id = 1 [
(com.util.meta) = {
needValidation: false,
fileMap: [
{
key: "t",
value: "raw_orders"
}
];
}];
}
The protobuf map is syntactic sugar for a repeated field of map entry messages with key and value fields. 1
In your case, your meta message
message MyMeta {
optional bool needValidation = 1;
map<string, string> fileMap = 2;
}
is equivalent to
message MyMeta {
optional bool needValidation = 1;
message FileMapEntry {
string key = 1;
string value = 2;
}
repeated FileMapEntry fileMap = 2;
}
Of course, it would be much nicer if there was a more obvious way to specify a map value in an option.
Seems it is not possible. To make my logic, I created a string like "StoreOrders:raw_orders_test,OrderItems:raw_order_items_test
message MyMeta {
int32 id = 1 [(com.util.meta).needValidation = false, (com.meta).tableOptions = "TableA:valueA,TableB:valueB;
}
and in my jav code and splitting the string to create a hash map.

How to properly format response object based on protobuf grpc specification

I have the following protobuf definition:
service MyService {
rpc ServiceMethod (ServiceMethodRequest) returns (ServiceMethodResponse) {}
}
message ServiceMethodRequest{
string requestParam = 1;
}
message ServiceMethodResponse{
Error error = 1;
SomeObjectList data = 2;
}
message Error{
string code = 1;
string errorMessage = 2;
}
message SomeObject {
string myobject = 1;
}
message SomeObjectList {
repeated SomeObject myobjects = 1;
}
As you can see I want to return formatted response so my API has some standardized way of responding. I formatted my response like this (this is in JSON format because of readability):
{"error":{"code":"-1","errorMessage":""},"data":{"myobjects":[{"myobject":"some string"},{"myobject":"another string"}]}}
But on the client side I am constantly getting:
{ Error: 2 UNKNOWN: Unknown Error
at Object.exports.createStatusError (.../node_modules/grpc/src/common.js:91:15)
at Object.onReceiveStatus (.../node_modules/grpc/src/client_interceptors.js:1204:28)
at InterceptingListener._callNext (.../node_modules/grpc/src/client_interceptors.js:568:42)
at InterceptingListener.onReceiveStatus (.../node_modules/grpc/src/client_interceptors.js:618:8)
at callback (.../node_modules/grpc/src/client_interceptors.js:845:24)
code: 2,
metadata: Metadata { _internal_repr: {}, flags: 0 },
details: 'Unknown Error' }
when I try to console.log response object.
What am I doing wrong?
Also, is there any good book on grpc with some examples (C, C#, Java, Python, JavaScript)?
Thanks in advance!
server.js
callback(null, message);

Resources