Skip to content
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

feat: Registry merging gogo and protov2 file descriptors #37

Merged
merged 21 commits into from
Feb 8, 2023

Conversation

amaury1093
Copy link
Contributor

@amaury1093 amaury1093 commented Feb 2, 2023

Merge gogo and protoregistry (protov2) file descriptors. Also expose them as a protodesc.Resolver.

Additionally, it performs at runtime the import path checks (same checks as in the protoc-gen-gogo generator).

For reviewers

  • Main file to review: proto/merge.go
  • Updated protobuf/google/protobuf/*.proto to v3.15.3 (the one that's in protobuf v1.28.1)
  • regenerate all files

Depends on :

Accompanying PR on the SDK:

proto/merge_test.go Outdated Show resolved Hide resolved
@amaury1093 amaury1093 marked this pull request as ready for review February 6, 2023 17:26
@amaury1093 amaury1093 requested a review from a team as a code owner February 6, 2023 17:26
Copy link
Member

@aaronc aaronc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some minor comments but generally LGTM

proto/merge.go Outdated Show resolved Hide resolved
proto/merge.go Outdated
protoregistry.GlobalFiles.RangeFiles(func(fileDescriptor protoreflect.FileDescriptor) bool {
fd := protodesc.ToFileDescriptorProto(fileDescriptor)
if err := CheckImportPath(*fd.Name, *fd.Package); err != nil {
panic(err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's collect any issues in a multi-error and then return it if it's non-empty rather than panicking

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's a multi-error? Just do some string concatenation with err.Error()?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

@amaury1093 amaury1093 Feb 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Talked offline to not use Go 1.20.

I'm not sure about introducing a new dependency here in gogo, seems overkill for this one error case. I used strings.Join with some line breaks instead, lmk if that works for you.

proto/merge.go Outdated
if found {
if !protov2.Equal(gogoFd, fd) {
diff := cmp.Diff(fd, gogoFd, protocmp.Transform())
panic(fmt.Errorf("got different file descriptors for %s; %s", *fd.Name, diff))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this error, I initially just returned a 1-line error. But when debugging this PR with the SDK, I found it useful to have the full diff. A snippet looks like:

got different file descriptors for cosmos/gov/v1beta1/tx.proto;   (*descriptorpb.FileDescriptorProto)(Inverse(protocmp.Transform, protocmp.Message{
// -- snip --
        	            	  					"number": int32(1),
        	            	  					"options": protocmp.Message{
        	            	  						"@type":                            s"google.protobuf.FieldOptions",
        	            	- 						"[cosmos_proto.accepts_interface]": string("Content"),
        	            	+ 						"[cosmos_proto.accepts_interface]": string("cosmos.gov.v1beta1.Content"),
        	            	  					},
        	            	  					"type":      s"TYPE_MESSAGE",
        	            	  					"type_name": string(".google.protobuf.Any"),
// -- snip --

The diff is verbose, so joining all errors in one go can be overwhelming and unreadable. I propose here to return one error at a time, with diff.

proto/merge.go Outdated Show resolved Hide resolved
proto/merge.go Outdated
// MergedRegistry returns a protodesc.Resolver that acts as a single registry
// which contains all the file descriptors registered with both gogoproto and
// protoregistry.
func MergedRegistry() (protodesc.Resolver, error) {
Copy link
Contributor Author

@amaury1093 amaury1093 Feb 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This returns a protodesc.Resolver, which is what protoregistry.GlobalFiles implements.

There's also a protodesc.MessageTypeResolver, which is what protoregistry.GlobalTypes implements (and used in the SDK).

Is there an easy wasy to go from Files to Types? Theoretically yes, but I didn't find any API in proto v2. Should I add a MergedTypes() function in this file too?

Copy link
Member

@aaronc aaronc Feb 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not that I know of... that would be quite hard I think

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use GlobalTypes in 3 instances in the SDK. What can we do if pulsar files are not registered?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where do we use? We can use dynamicpb

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For AppConfig I guess we can use the merged registry if we need to support gogo there

For textual we should allow parameterizing the type resolver and also default to dynamicpb if not found

Comment on lines 758 to 764
// "google.protobuf" pacakges all have different go package names
// (typepb, structpb, anypb...), so running protoc here will error.
// As a hack, we skip them here. It should be safe, as they packages
// are generated internally in this repo.
if *f.Package == "google.protobuf" {
continue
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, here's another hack unfortunately. when running protoc-gen-gogo on google.protobuf.* stuff in this repo, I get an error with inconsistent go package names. This is expected, the new proto files are generated in separate packages: anypb, durationpb...

So the hack is to skip validation for google.protobuf.*. Then in the Makefile, I do sed to modify the package name

Copy link
Member

@aaronc aaronc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

@amaury1093
Copy link
Contributor Author

I'm going to go ahead and merge this. In cosmos/cosmos-sdk#14886 I still got some file descriptor mismatches, but afaict they are all SDK proto files, not gogo's. So this PR should be fine.

Let's not tag a new gogo version asap, but wait until the SDK PR is r4r.

@amaury1093 amaury1093 merged commit e7c6f1d into main Feb 8, 2023
@amaury1093 amaury1093 deleted the am/single-registry branch February 8, 2023 14:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants