if _, ok := protoTypes[name]; ok {
// TODO: Some day, make this a panic.
log.Printf("proto: duplicate proto type registered: %s", name)
return
}
I have duplicate messages, why is that bad? If my application has more than one adapter that speaks to some outside systems also using protocol buffers, why shouldn't I keep separate definitions of the messages for each adapter/rpc source. The fact the messages are named the same is coincidence because at any moment they can diverge.
If endpoint A has a message named messageA and endpoint B also has messageA then that happened coincidently; its very likely that endpointB may diverge in the future and change the name to messageB. I would like to protect myself from these changes by having separate message definitions (regardless if they happen to have the same name/signatures as other messages in the system) in separate namespaces for their respective rpc handlers. At the moment, I have to define messages along my whole application boundary, instead of being able to vary by namespace. Right?
The proto world requires you to use distinct names, package-qualified. The message names can be the same, but you should use different package names to keep them isolated.
-app
-lib
-port
-- endpoint1
---- resources
------ proto
-------- m1.pb.go // package proto;
-------- m2.pb.go // package proto;
------ thrift
------ gob
-- endpoint2
---- resources
------ proto
-------- m1.pb.go // package proto;
-------- m2.pb.go // package proto;
------ thrift
That sucks that I have to call endpoint2/resources/proto package something else just to 'qualify' the name for protobuf.
Sorry, but that's not anything that the Go protobuf support has decided. It's a protobuf thing. There's a global namespace.
A package name of "proto" is pretty bad. It's like calling a Go package "pkg". Consider naming them endpoint1 and endpoint2, or something even more descriptive.
Can you give me an example of the full package name you would use for m1.pb.go in endpoint1 and m1.pb.go in endpoint2? Thanks.
I suggested using "endpoint1" as the package name for the first. But this is very abstract; if you have a specific case to point me at then I may be able to be more specific.
I created an example repo with the structure in question. https://github.com/SephVelut/proto-namespace-issue. Its all empty except for the port dir, which contains the .proto message files. The idea being a port adapter can vary encodings (proto, thrift, gob etc) but only use definitions within its own namespace, which might even have the same signature/naming as other definitions in other packages. I want to avoid having global definitions.
It looks like you could use package commander in port/commander/resources/proto/protocol.proto (making commander.Tcp, etc.), and package publishing in port/publishing/resources/proto/protocol.proto (making publishing.Tcp, etc.).
I've been facing a very similar issue, and it was related to a cycling dependency import statement.
So a import statement that imports a package that resides inside the proto compiled dir can cause the error: error: proto: duplicate proto type registered test2
The import that caused cycling dependency was something like this:
"github.com/test/test1/proto/github.com/test/test1/test2"
The correct import should not contain /proto
"github.com/test/test1/test2"
And this fixed the error.
Cheers.
Most helpful comment
The proto world requires you to use distinct names, package-qualified. The message names can be the same, but you should use different package names to keep them isolated.