-
Notifications
You must be signed in to change notification settings - Fork 153
Remove pack/1 and unpack/2 from Protobuf.Any #329
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Could the |
|
@yordis can you expand on the kind of manual mapping you have to do and why it's a lot of work/a headache? |
|
We need to extract the Full Name in order to use the value as the event type in the event store events table, and in the message bus we would use Without "Full Name" function, this requires a lot of manual entry of information (unless I am doing something wrong, I am all ears), while in other programming languages that is taken care of (we are polyglot btw, Elixir, Go, TS at the moment). Just one subdomain alone has 11 events, and 5 commands; syntax = "proto3";
package messagebus.v1;
import "google/protobuf/any.proto";
import "google/protobuf/timestamp.proto";
message Command {
string id = 1;
google.protobuf.Any data = 3;
map<string, string> metadata = 4;
google.protobuf.Timestamp created_at = 5;
string correlation_id = 6;
string causation_id = 7;
}syntax = "proto3";
package myapp.v1;
message MyCommand {
string command_id = 1;
}
message MyEventName {
string event_id = 1;
}
message Event {
oneof event {
MyEventName my_event_name = 1;
}
}func eventTypeProvider(event *eventv1.Event) (*string, error) {
switch e := event.Event.(type) {
case *eventv1.Event_MyEventName:
// myapp.v1.MyEventName
return MessageFullName(e.MyEventName)
default:
return nil, trogon.ErrUnknownEvent
}
}
func MessageFullName[Message protoreflect.ProtoMessage](msg Message) string {
return msg.ProtoReflect().Descriptor().FullName()
}func TestExample(t *testing.T) {
anymsg, err := anypb.New(&myappv1.MyCommand{
CommandId: "123",
})
require.NoError(t, err)
message := messagebus.CommandMessage{Data: anymsg}
marshal, err := protojson.Marshal(&message)
require.NoError(t, err)
fmt.Sprintf("%v", string(marshal))
// {"data":{"@type":"type.googleapis.com/myapp.v1.MyCommand", "commandId":"123"}}
eventype, err := eventTypeProvider(&myappv1.Event{
Event: &myappv1.Event_MyEventName{
MyEventName: &myappv1.MyEventName{
EventId: "123",
},
},
})
require.NoError(t, err)
fmt.Sprintf("%v", eventype)
// myapp.v1.MyEventName
}
func eventTypeProvider(event *myappv1.Event) (string, error) {
switch e := event.Event.(type) {
case *myappv1.Event_MyEventName:
return MessageFullName(e.MyEventName), nil
default:
return "", ErrUnknownEvent
}
}
func MessageFullName[Message protoreflect.ProtoMessage](msg Message) string {
return string(msg.ProtoReflect().Descriptor().FullName())
}https://pkg.go.dev/google.golang.org/protobuf/types/known/anypb#MarshalFrom // MarshalFrom marshals src into dst as the underlying message
// using the provided marshal options.
//
// If no options are specified, call dst.MarshalFrom instead.
func MarshalFrom(dst *Any, src proto.Message, opts proto.MarshalOptions) error {
const urlPrefix = "type.googleapis.com/"
if src == nil {
return protoimpl.X.NewError("invalid nil source message")
}
b, err := opts.Marshal(src)
if err != nil {
return err
}
dst.TypeUrl = urlPrefix + string(src.ProtoReflect().Descriptor().FullName())
dst.Value = b
return nil
}Usage in,
|
|
Is |
That is what other SDKs are doing, and everything works around such value when dealing with Any, so it is expected to be deterministic value.
It confused me as well, I was trying to find information about what was the precise problem as well to make sure I understood the problem, I am coming from the perspective that other SDKs do not have such issue, as far as I can tell |
The idea here is to push people to use
Google.Protobuf.Anydirectly more. The defaulttype_urlcan be written down manually, and it's probably going to be a lot more accurate.I'm thinking of removing
Protobuf.Any.type_url_to_module/1too and make it a private function in this library instead of part of the public API. Thoughts @ericmj?