Description
Is your feature request related to a problem? Please describe.
The protoregistry
is a very powerful tool that allows users to register their own types at runtime. I have made use of this feature along with protojson.UnmarshalOptions
to supply my own Resolver
that is backed by a protoregistry.Types
that I fill dynamically with my own types.
Unfortunately I am also using any.Any
within my message to specify a generic "payload" and when I come to unmarshal that payload I receive err == protoregistry.NotFound
.
var x ptypes.DynamicAny
if err := ptypes.UnmarshalAny(a, &x); err != nil { ... }
fmt.Printf("unmarshaled message: %v", x.Message)
This is due to the use of the protoregistry.GlobalTypes
inside ptypes.Empty
(which in turn is used by ptypes.UnmarshalAny
to generate an empty proto.Message
for the type inside the TypeURL
of the Any
message).
As described below, I want to be able to inject my own registry and not rely on the global one for resolution.
Describe the solution you'd like
I have one way forward and two places it can be added, the solution is to add an UnmarshalAnyOptions
/MarshalAnyOptions
with a Resolver
interface that can be supplied by the user, exactly the same as the implementation in protojson
.
- Refactor the api inside
ptypes/any.go
(I assume you do not want to do this) - Add this new functionality to the v2 API types package
Describe alternatives you've considered
I briefly considered using protoregistry.GlobalTypes
throughout my application, but it does not support the following use case:
I have a new version of an existing MessageType (maybe with a field added) that needs to be registered that I want to replace the existing type.
The protoregistry.GlobalTypes
does not support this because I cannot remove the old entry and if I register the new type it will be ignored with a type already registered error.
An alternative solution would be to extend the protoregistry.GlobalTypes to support removal/replacement of types, but this is a much larger change than the one I have proposed here. (although maybe necessary in future).
For now I have simply copied the UnmarshalAny / AnyMessage / Empty methods from the source into my application, where I can use my own registry instead of protoregistry.GlobalTypes
.
Additional context
I am attempting to build a dynamic registry similar to the one mentioned in this tech blog by Deliveroo.
I am using this parser to read the protos from a GCS bucket when they are uploaded, and then using them to validate that the structure of incoming events is correct.
I am happy to provide a sample repository if the explanation given here is not sufficient to debug this issue.