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

Introduce MethodDescriptorSupplier #3086

Closed
wants to merge 3 commits into from

Conversation

lukaszx0
Copy link
Collaborator

Second iteration on providing an easier way to access service methods which I took stab at in #2904.

It introduces new MethodDescriptorSupplier and MethodDescriptor#setSchemaDescriptor.

cc @ejona86

@lukaszx0
Copy link
Collaborator Author

(Splitted into two commit as per @ejona86's suggestion)

@ejona86
Copy link
Member

ejona86 commented Jun 12, 2017

This looks fine to me, other than issues with how the commits were split. Those can either be resolved by reworking what is in each commit or by squashing.

@zhangkun83, @carl-mastrangelo, @dapengzhang0, It's important to note that the new APIs introduced to MethodDescriptor, ProtoServiceDescriptorSupplier, and ProtoMethodDescriptorSupplier can't be @ExperimentalApi since they are used by the codegen. The change to MethodDescriptor is a copy of what is already in ServiceDescriptor.

CC @ericgribkoff

@@ -38,6 +38,7 @@ private BenchmarkServiceGrpc() {}
io.grpc.benchmarks.proto.Messages.SimpleRequest.getDefaultInstance()))
.setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
io.grpc.benchmarks.proto.Messages.SimpleResponse.getDefaultInstance()))
.setSchemaDescriptor(new BenchmarkServiceFileDescriptorSupplier().getServiceDescriptor().findMethodByName("UnaryCall"))
Copy link
Member

Choose a reason for hiding this comment

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

This should have just been .setSchemaDescriptor(new BenchmarkServiceFileDescriptorSupplier())

/**
* Provides access to the underlying proto service descriptor.
*/
public interface ProtoServiceDescriptorSupplier extends ProtoFileDescriptorSupplier {
Copy link
Member

Choose a reason for hiding this comment

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

I had intended that this would be in the second commit as well.

@lukaszx0
Copy link
Collaborator Author

@ejona86 squashing will be easier if that works?

@lukaszx0
Copy link
Collaborator Author

@ejona86 rebased and squashed into one commit.

/**
* Provides access to the underlying proto service method descriptor.
*/
public interface ProtoMethodDescriptorSupplier {
Copy link
Member

Choose a reason for hiding this comment

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

Extend ProtoServiceDescriptorSupplier?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done

@dapengzhang0
Copy link
Member

LGTM

"private static final class $proto_method_descriptor_supplier$ extends $proto_file_descriptor_supplier$ implements $ProtoMethodDescriptorSupplier$ {\n");
p->Indent();
p->Print(*vars, "private final String methodName;\n\n");
p->Print(*vars, "public $proto_method_descriptor_supplier$(String methodName) {\n");
Copy link
Contributor

Choose a reason for hiding this comment

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

private

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done

}
}

private static final class BenchmarkServiceMethodDescriptorSupplier extends BenchmarkServiceFileDescriptorSupplier implements io.grpc.protobuf.ProtoMethodDescriptorSupplier {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why extend? What if the service descriptor isn't available? Services have-a set of methods. Methods fail the is-a test. So too with the supplier.

Perhaps a method could be added to get the serviceDescriptorSupplier for the method?

Copy link
Member

Choose a reason for hiding this comment

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

protobuf's MethodDescriptor.getService() is guaranteed to work.

@@ -42,6 +42,7 @@
private final String fullMethodName;
private final Marshaller<ReqT> requestMarshaller;
private final Marshaller<RespT> responseMarshaller;
private final Object schemaDescriptor;
Copy link
Contributor

Choose a reason for hiding this comment

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

@Nullable

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done

*
* @since 1.5.0
*/
public Object getSchemaDescriptor() {
Copy link
Contributor

Choose a reason for hiding this comment

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

@Nullable

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done

/**
* Provides access to the underlying proto service method descriptor.
*/
public interface ProtoMethodDescriptorSupplier {
Copy link
Contributor

Choose a reason for hiding this comment

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

@DoNotMock

Copy link
Member

Choose a reason for hiding this comment

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

DoNotMock an interface? What would break?

/**
* Returns method descriptor to the proto service method.
*/
MethodDescriptor getMethodDescriptor();
Copy link
Contributor

Choose a reason for hiding this comment

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

@CheckReturnValue

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done


p->Print(
*vars,
"private static final class $proto_method_descriptor_supplier$ extends $proto_file_descriptor_supplier$ implements $ProtoMethodDescriptorSupplier$ {\n");
Copy link
Contributor

Choose a reason for hiding this comment

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

So far grpc generated code is fairly readable. One of the things that makes it that way is generally fitting within line limits. Until we auto format code, could this be wrapped to try to fit? Google style is binary ops go on the following line. Something like:

class Foo
    extends Bar
    implements Baz

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done

@carl-mastrangelo
Copy link
Contributor

I'm curious how this will interact with the existing schema objects for marshallers. What should the relationship be? (can one be null but not the other? Vice-versa?, Should marshaller schema be removed?)

@ejona86
Copy link
Member

ejona86 commented Jun 20, 2017

@carl-mastrangelo, there aren't schema objects for marshallers. There are schema objects for services though. It seems necessary to have a separate places to store them. We could use the same schema object for both, though (although then it takes more work to lookup the proto MethodDescriptor).

@lukaszx0
Copy link
Collaborator Author

@carl-mastrangelo addressed your comments, PTAL

@ejona86
Copy link
Member

ejona86 commented Jul 20, 2017

@carl-mastrangelo, ping

@@ -392,11 +396,32 @@ public void invoke(Req request, io.grpc.stub.StreamObserver<Resp> responseObserv
}
}

private static final class WorkerServiceDescriptorSupplier implements io.grpc.protobuf.ProtoFileDescriptorSupplier {
private static class WorkerServiceFileDescriptorSupplier
Copy link
Contributor

Choose a reason for hiding this comment

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

I would prefer if this class could be final, since every other class in this generate code is final too.

What do you think about making this final, making a static instance on the MethodDescriptorSupplier, and having MethodDescriptorSupplier implement the interfaces here?

(non final classes, even private ones can be mocked by spying instances of them. This was the cause of a recent test breakage)

@java.lang.Override
public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() {
return io.grpc.benchmarks.proto.Services.getDescriptor();
}

Copy link
Contributor

Choose a reason for hiding this comment

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

This need a package-private constructor. A private ctor causes synthetic classes to be made, and a public one makes reflection too easy.

implements io.grpc.protobuf.ProtoMethodDescriptorSupplier {
private final String methodName;

private WorkerServiceMethodDescriptorSupplier(String methodName) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be package-protected too.

extends WorkerServiceFileDescriptorSupplier
implements io.grpc.protobuf.ProtoMethodDescriptorSupplier {
private final String methodName;

Copy link
Contributor

Choose a reason for hiding this comment

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

Another alternative would be to nest the MethodDescriptorSupplier class as an inner class of the FileDescriptorSupplier class, and let it capture the fields and methods.

@ejona86
Copy link
Member

ejona86 commented Aug 10, 2017

@lukaszx0, it seems there are only small changes remaining. Want to fix them up, or us to?

@ejona86
Copy link
Member

ejona86 commented Aug 25, 2017

@carl-mastrangelo, PTAL. Does this work for you? I created a base abstract class and extend it for both file and method descriptors, which are then both final.

I also took the liberty to make java_generator.cpp use a giant string for the block of code, which makes it much more readable and easier to modify for me.

@ejona86
Copy link
Member

ejona86 commented Sep 1, 2017

@carl-mastrangelo, friendly ping.

* sets this value, in order to be consumed by the server reflection service. See also:
* {@code io.grpc.protobuf.ProtoMethodDescriptorSupplier}.
*
* @since 1.5.0
Copy link
Contributor

Choose a reason for hiding this comment

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

1.7.0

Copy link
Contributor

@carl-mastrangelo carl-mastrangelo left a comment

Choose a reason for hiding this comment

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

A few minor comments but LGTM


/**
* Provides access to the underlying proto service method descriptor.
*/
Copy link
Contributor

Choose a reason for hiding this comment

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

Would you mind adding a @Since here too?


/**
* Provides access to the underlying proto service descriptor.
*/
Copy link
Contributor

Choose a reason for hiding this comment

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

And here?

@ejona86
Copy link
Member

ejona86 commented Sep 8, 2017

@carl-mastrangelo, can you review #3451? It includes the fixes requested (plus another one I noticed). I couldn't push to lukaszx0's branch, so I needed to create a new PR.

@ejona86
Copy link
Member

ejona86 commented Sep 11, 2017

Merged as part of #3451

@ejona86 ejona86 closed this Sep 11, 2017
@lock lock bot locked and limited conversation to collaborators Sep 21, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants