core: make ServiceDescriptor use the Builder pattern

This commit is contained in:
Carl Mastrangelo 2017-01-30 15:22:40 -08:00 committed by GitHub
parent e08034cde0
commit 237a65ebfc
19 changed files with 233 additions and 115 deletions

View File

@ -277,11 +277,11 @@ public class BenchmarkServiceGrpc {
synchronized (BenchmarkServiceGrpc.class) {
result = serviceDescriptor;
if (result == null) {
serviceDescriptor = result = new io.grpc.ServiceDescriptor(
SERVICE_NAME,
new BenchmarkServiceDescriptorSupplier(),
METHOD_UNARY_CALL,
METHOD_STREAMING_CALL);
serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME)
.setSchemaDescriptor(new BenchmarkServiceDescriptorSupplier())
.addMethod(METHOD_UNARY_CALL)
.addMethod(METHOD_STREAMING_CALL)
.build();
}
}
}

View File

@ -395,13 +395,13 @@ public class WorkerServiceGrpc {
synchronized (WorkerServiceGrpc.class) {
result = serviceDescriptor;
if (result == null) {
serviceDescriptor = result = new io.grpc.ServiceDescriptor(
SERVICE_NAME,
new WorkerServiceDescriptorSupplier(),
METHOD_RUN_SERVER,
METHOD_RUN_CLIENT,
METHOD_CORE_COUNT,
METHOD_QUIT_WORKER);
serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME)
.setSchemaDescriptor(new WorkerServiceDescriptorSupplier())
.addMethod(METHOD_RUN_SERVER)
.addMethod(METHOD_RUN_CLIENT)
.addMethod(METHOD_CORE_COUNT)
.addMethod(METHOD_QUIT_WORKER)
.build();
}
}
}

View File

@ -930,21 +930,20 @@ static void PrintGetServiceDescriptorMethod(const ServiceDescriptor* service,
p->Print(
*vars,
"serviceDescriptor = result = new $ServiceDescriptor$(\n");
"serviceDescriptor = result = $ServiceDescriptor$.newBuilder(SERVICE_NAME)");
p->Indent();
p->Indent();
p->Print("SERVICE_NAME");
if (flavor == ProtoFlavor::NORMAL) {
p->Print(
*vars,
",\nnew $proto_descriptor_supplier$()");
"\n.setSchemaDescriptor(new $proto_descriptor_supplier$())");
}
for (int i = 0; i < service->method_count(); ++i) {
const MethodDescriptor* method = service->method(i);
(*vars)["method_field_name"] = MethodPropertiesFieldName(method);
p->Print(*vars, ",\n$method_field_name$");
p->Print(*vars, "\n.addMethod($method_field_name$)");
}
p->Print(");\n");
p->Print("\n.build();\n");
p->Outdent();
p->Outdent();

View File

@ -440,14 +440,14 @@ public class TestServiceGrpc {
synchronized (TestServiceGrpc.class) {
result = serviceDescriptor;
if (result == null) {
serviceDescriptor = result = new io.grpc.ServiceDescriptor(
SERVICE_NAME,
new TestServiceDescriptorSupplier(),
METHOD_UNARY_CALL,
METHOD_STREAMING_OUTPUT_CALL,
METHOD_STREAMING_INPUT_CALL,
METHOD_FULL_BIDI_CALL,
METHOD_HALF_BIDI_CALL);
serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME)
.setSchemaDescriptor(new TestServiceDescriptorSupplier())
.addMethod(METHOD_UNARY_CALL)
.addMethod(METHOD_STREAMING_OUTPUT_CALL)
.addMethod(METHOD_STREAMING_INPUT_CALL)
.addMethod(METHOD_FULL_BIDI_CALL)
.addMethod(METHOD_HALF_BIDI_CALL)
.build();
}
}
}

View File

@ -433,13 +433,13 @@ public class TestServiceGrpc {
synchronized (TestServiceGrpc.class) {
result = serviceDescriptor;
if (result == null) {
serviceDescriptor = result = new io.grpc.ServiceDescriptor(
SERVICE_NAME,
METHOD_UNARY_CALL,
METHOD_STREAMING_OUTPUT_CALL,
METHOD_STREAMING_INPUT_CALL,
METHOD_FULL_BIDI_CALL,
METHOD_HALF_BIDI_CALL);
serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME)
.addMethod(METHOD_UNARY_CALL)
.addMethod(METHOD_STREAMING_OUTPUT_CALL)
.addMethod(METHOD_STREAMING_INPUT_CALL)
.addMethod(METHOD_FULL_BIDI_CALL)
.addMethod(METHOD_HALF_BIDI_CALL)
.build();
}
}
}

View File

@ -511,13 +511,13 @@ public class TestServiceGrpc {
synchronized (TestServiceGrpc.class) {
result = serviceDescriptor;
if (result == null) {
serviceDescriptor = result = new io.grpc.ServiceDescriptor(
SERVICE_NAME,
METHOD_UNARY_CALL,
METHOD_STREAMING_OUTPUT_CALL,
METHOD_STREAMING_INPUT_CALL,
METHOD_FULL_BIDI_CALL,
METHOD_HALF_BIDI_CALL);
serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME)
.addMethod(METHOD_UNARY_CALL)
.addMethod(METHOD_STREAMING_OUTPUT_CALL)
.addMethod(METHOD_STREAMING_INPUT_CALL)
.addMethod(METHOD_FULL_BIDI_CALL)
.addMethod(METHOD_HALF_BIDI_CALL)
.build();
}
}
}

View File

@ -32,49 +32,64 @@
package io.grpc;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Preconditions;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.Nullable;
/**
* Descriptor for a service.
*
* @since 1.0.0
*/
public final class ServiceDescriptor {
private final String name;
private final Collection<MethodDescriptor<?, ?>> methods;
private final Object marshallerDescriptor;
private final Object schemaDescriptor;
/**
* Constructs a new Service Descriptor. Users are encouraged to use {@link #newBuilder}
* instead.
*
* @param name The name of the service
* @param methods The methods that are part of the service
* @since 1.0.0
*/
public ServiceDescriptor(String name, MethodDescriptor<?, ?>... methods) {
this(name, null, Arrays.asList(methods));
this(name, Arrays.asList(methods));
}
/**
* Constructs a new Service Descriptor. Users are encouraged to use {@link #newBuilder}
* instead.
*
* @param name The name of the service
* @param methods The methods that are part of the service
* @since 1.0.0
*/
public ServiceDescriptor(String name, Collection<MethodDescriptor<?, ?>> methods) {
this(name, null, methods);
this(newBuilder(name).addAllMethods(checkNotNull(methods, "methods")));
}
public ServiceDescriptor(String name, Object marshallerDescriptor,
MethodDescriptor<?, ?>... methods) {
this(name, marshallerDescriptor, Arrays.asList(methods));
private ServiceDescriptor(Builder b) {
this.name = b.name;
validateMethodNames(name, b.methods);
this.methods = Collections.unmodifiableList(new ArrayList<MethodDescriptor<?, ?>>(b.methods));
this.schemaDescriptor = b.schemaDescriptor;
}
/** Creates a new ServiceDescriptor. */
public ServiceDescriptor(String name, Object marshallerDescriptor,
Collection<MethodDescriptor<?, ?>> methods) {
this.name = Preconditions.checkNotNull(name, "name");
Preconditions.checkNotNull(methods, "methods");
validateMethodNames(name, methods);
this.marshallerDescriptor = marshallerDescriptor;
this.methods = Collections.unmodifiableList(new ArrayList<MethodDescriptor<?, ?>>(methods));
}
/** Simple name of the service. It is not an absolute path. */
/**
* Simple name of the service. It is not an absolute path.
*
* @since 1.0.0
*/
public String getName() {
return name;
}
@ -82,24 +97,33 @@ public final class ServiceDescriptor {
/**
* A collection of {@link MethodDescriptor} instances describing the methods exposed by the
* service.
*
* @since 1.0.0
*/
public Collection<MethodDescriptor<?, ?>> getMethods() {
return methods;
}
/**
* Returns a marshaller-specific object that provides additional information about the service.
* For example, when using Protobuf this should generally be a
* {@link io.grpc.protobuf.ProtoFileDescriptorSupplier}, when present.
* Returns the schema descriptor for this service. A schema descriptor is an object that is not
* used by gRPC core but includes information related to the service. The type of the object
* is specific to the consumer, so both the code setting the schema descriptor and the code
* calling {@link #getSchemaDescriptor()} must coordinate. For example, protobuf generated code
* sets this value, in order to be consumed by the server reflection service. See also:
* {@code io.grpc.protobuf.ProtoFileDescriptorSupplier}.
*
* @since 1.1.0
*/
@Nullable
public Object getMarshallerDescriptor() {
return marshallerDescriptor;
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/2666")
public Object getSchemaDescriptor() {
return schemaDescriptor;
}
static void validateMethodNames(String serviceName, Collection<MethodDescriptor<?, ?>> methods) {
Set<String> allNames = new HashSet<String>(methods.size());
for (MethodDescriptor<?, ?> method : methods) {
checkNotNull(method, "method");
String methodServiceName =
MethodDescriptor.extractFullServiceName(method.getFullMethodName());
checkArgument(serviceName.equals(methodServiceName),
@ -108,4 +132,91 @@ public final class ServiceDescriptor {
"duplicate name %s", method.getFullMethodName());
}
}
/**
* Creates a new builder for a {@link ServiceDescriptor}.
*
* @since 1.1.0
*/
public static Builder newBuilder(String name) {
return new Builder(name);
}
/**
* A builder for a {@link ServiceDescriptor}.
*
* @since 1.1.0
*/
public static final class Builder {
private Builder(String name) {
setName(name);
}
private String name;
private List<MethodDescriptor<?, ?>> methods = new ArrayList<MethodDescriptor<?, ?>>();
private Object schemaDescriptor;
/**
* Sets the name. This should be non-{@code null}.
*
* @param name The name of the service.
* @return this builder.
* @since 1.1.0
*/
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/2666")
public Builder setName(String name) {
this.name = checkNotNull(name, "name");
return this;
}
/**
* Adds a method to this service. This should be non-{@code null}.
*
* @param method the method to add to the descriptor.
* @return this builder.
* @since 1.1.0
*/
public Builder addMethod(MethodDescriptor<?, ?> method) {
methods.add(checkNotNull(method, "method"));
return this;
}
/**
* Currently not exposed. Bulk adds methods to this builder.
*
* @param methods the methods to add.
* @return this builder.
*/
private Builder addAllMethods(Collection<MethodDescriptor<?, ?>> methods) {
this.methods.addAll(methods);
return this;
}
/**
* Sets the schema descriptor for this builder. A schema descriptor is an object that is not
* used by gRPC core but includes information related to the service. The type of the object
* is specific to the consumer, so both the code calling this and the code calling
* {@link ServiceDescriptor#getSchemaDescriptor()} must coordinate. For example, protobuf
* generated code sets this value, in order to be consumed by the server reflection service.
*
* @param schemaDescriptor an object that describes the service structure. Should be immutable.
* @return this builder.
* @since 1.1.0
*/
public Builder setSchemaDescriptor(@Nullable Object schemaDescriptor) {
this.schemaDescriptor = schemaDescriptor;
return this;
}
/**
* Constructs a new {@link ServiceDescriptor}. {@link #setName} should have been called with a
* non-{@code null} value before calling this.
*
* @return a new ServiceDescriptor
* @since 1.1.0
*/
public ServiceDescriptor build() {
return new ServiceDescriptor(this);
}
}
}

View File

@ -56,7 +56,7 @@ public class ServiceDescriptorTest {
thrown.expect(NullPointerException.class);
thrown.expectMessage("name");
new ServiceDescriptor(null, Collections.emptyList());
new ServiceDescriptor(null, Collections.<MethodDescriptor<?, ?>>emptyList());
}
@Test
@ -67,6 +67,14 @@ public class ServiceDescriptorTest {
new ServiceDescriptor("name", (Collection<MethodDescriptor<?, ?>>) null);
}
@Test
public void failsOnNullMethod() {
thrown.expect(NullPointerException.class);
thrown.expectMessage("method");
new ServiceDescriptor("name", (Collections.<MethodDescriptor<?, ?>>singletonList(null)));
}
@Test
public void failsOnNonMatchingNames() {
thrown.expect(IllegalArgumentException.class);

View File

@ -208,10 +208,10 @@ public class LoadBalancerGrpc {
synchronized (LoadBalancerGrpc.class) {
result = serviceDescriptor;
if (result == null) {
serviceDescriptor = result = new io.grpc.ServiceDescriptor(
SERVICE_NAME,
new LoadBalancerDescriptorSupplier(),
METHOD_BALANCE_LOAD);
serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME)
.setSchemaDescriptor(new LoadBalancerDescriptorSupplier())
.addMethod(METHOD_BALANCE_LOAD)
.build();
}
}
}

View File

@ -218,10 +218,10 @@ public class HealthGrpc {
synchronized (HealthGrpc.class) {
result = serviceDescriptor;
if (result == null) {
serviceDescriptor = result = new io.grpc.ServiceDescriptor(
SERVICE_NAME,
new HealthDescriptorSupplier(),
METHOD_CHECK);
serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME)
.setSchemaDescriptor(new HealthDescriptorSupplier())
.addMethod(METHOD_CHECK)
.build();
}
}
}

View File

@ -210,10 +210,10 @@ public class ServerReflectionGrpc {
synchronized (ServerReflectionGrpc.class) {
result = serviceDescriptor;
if (result == null) {
serviceDescriptor = result = new io.grpc.ServiceDescriptor(
SERVICE_NAME,
new ServerReflectionDescriptorSupplier(),
METHOD_SERVER_REFLECTION_INFO);
serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME)
.setSchemaDescriptor(new ServerReflectionDescriptorSupplier())
.addMethod(METHOD_SERVER_REFLECTION_INFO)
.build();
}
}
}

View File

@ -245,10 +245,10 @@ public class AnotherDynamicServiceGrpc {
synchronized (AnotherDynamicServiceGrpc.class) {
result = serviceDescriptor;
if (result == null) {
serviceDescriptor = result = new io.grpc.ServiceDescriptor(
SERVICE_NAME,
new AnotherDynamicServiceDescriptorSupplier(),
METHOD_METHOD);
serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME)
.setSchemaDescriptor(new AnotherDynamicServiceDescriptorSupplier())
.addMethod(METHOD_METHOD)
.build();
}
}
}

View File

@ -245,10 +245,10 @@ public class DynamicServiceGrpc {
synchronized (DynamicServiceGrpc.class) {
result = serviceDescriptor;
if (result == null) {
serviceDescriptor = result = new io.grpc.ServiceDescriptor(
SERVICE_NAME,
new DynamicServiceDescriptorSupplier(),
METHOD_METHOD);
serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME)
.setSchemaDescriptor(new DynamicServiceDescriptorSupplier())
.addMethod(METHOD_METHOD)
.build();
}
}
}

View File

@ -218,10 +218,10 @@ public class ReflectableServiceGrpc {
synchronized (ReflectableServiceGrpc.class) {
result = serviceDescriptor;
if (result == null) {
serviceDescriptor = result = new io.grpc.ServiceDescriptor(
SERVICE_NAME,
new ReflectableServiceDescriptorSupplier(),
METHOD_METHOD);
serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME)
.setSchemaDescriptor(new ReflectableServiceDescriptorSupplier())
.addMethod(METHOD_METHOD)
.build();
}
}
}

View File

@ -337,10 +337,10 @@ public final class ProtoReflectionService extends ServerReflectionGrpc.ServerRef
List<ServerServiceDefinition> currentMutableServices = server.getMutableServices();
for (ServerServiceDefinition mutableService : currentMutableServices) {
io.grpc.ServiceDescriptor serviceDescriptor = mutableService.getServiceDescriptor();
if (serviceDescriptor.getMarshallerDescriptor() instanceof ProtoFileDescriptorSupplier) {
if (serviceDescriptor.getSchemaDescriptor() instanceof ProtoFileDescriptorSupplier) {
String serviceName = serviceDescriptor.getName();
FileDescriptor fileDescriptor =
((ProtoFileDescriptorSupplier) serviceDescriptor.getMarshallerDescriptor())
((ProtoFileDescriptorSupplier) serviceDescriptor.getSchemaDescriptor())
.getFileDescriptor();
currentFileDescriptors.add(fileDescriptor);
checkState(!currentServiceNames.contains(serviceName),
@ -433,9 +433,9 @@ public final class ProtoReflectionService extends ServerReflectionGrpc.ServerRef
Set<String> seenFiles = new HashSet<String>();
for (ServerServiceDefinition service : services) {
io.grpc.ServiceDescriptor serviceDescriptor = service.getServiceDescriptor();
if (serviceDescriptor.getMarshallerDescriptor() instanceof ProtoFileDescriptorSupplier) {
if (serviceDescriptor.getSchemaDescriptor() instanceof ProtoFileDescriptorSupplier) {
FileDescriptor fileDescriptor =
((ProtoFileDescriptorSupplier) serviceDescriptor.getMarshallerDescriptor())
((ProtoFileDescriptorSupplier) serviceDescriptor.getSchemaDescriptor())
.getFileDescriptor();
String serviceName = serviceDescriptor.getName();
checkState(!serviceNames.contains(serviceName),

View File

@ -286,11 +286,11 @@ public class MetricsServiceGrpc {
synchronized (MetricsServiceGrpc.class) {
result = serviceDescriptor;
if (result == null) {
serviceDescriptor = result = new io.grpc.ServiceDescriptor(
SERVICE_NAME,
new MetricsServiceDescriptorSupplier(),
METHOD_GET_ALL_GAUGES,
METHOD_GET_GAUGE);
serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME)
.setSchemaDescriptor(new MetricsServiceDescriptorSupplier())
.addMethod(METHOD_GET_ALL_GAUGES)
.addMethod(METHOD_GET_GAUGE)
.build();
}
}
}

View File

@ -284,11 +284,11 @@ public class ReconnectServiceGrpc {
synchronized (ReconnectServiceGrpc.class) {
result = serviceDescriptor;
if (result == null) {
serviceDescriptor = result = new io.grpc.ServiceDescriptor(
SERVICE_NAME,
new ReconnectServiceDescriptorSupplier(),
METHOD_START,
METHOD_STOP);
serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME)
.setSchemaDescriptor(new ReconnectServiceDescriptorSupplier())
.addMethod(METHOD_START)
.addMethod(METHOD_STOP)
.build();
}
}
}

View File

@ -571,16 +571,16 @@ public class TestServiceGrpc {
synchronized (TestServiceGrpc.class) {
result = serviceDescriptor;
if (result == null) {
serviceDescriptor = result = new io.grpc.ServiceDescriptor(
SERVICE_NAME,
new TestServiceDescriptorSupplier(),
METHOD_EMPTY_CALL,
METHOD_UNARY_CALL,
METHOD_STREAMING_OUTPUT_CALL,
METHOD_STREAMING_INPUT_CALL,
METHOD_FULL_DUPLEX_CALL,
METHOD_HALF_DUPLEX_CALL,
METHOD_UNIMPLEMENTED_CALL);
serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME)
.setSchemaDescriptor(new TestServiceDescriptorSupplier())
.addMethod(METHOD_EMPTY_CALL)
.addMethod(METHOD_UNARY_CALL)
.addMethod(METHOD_STREAMING_OUTPUT_CALL)
.addMethod(METHOD_STREAMING_INPUT_CALL)
.addMethod(METHOD_FULL_DUPLEX_CALL)
.addMethod(METHOD_HALF_DUPLEX_CALL)
.addMethod(METHOD_UNIMPLEMENTED_CALL)
.build();
}
}
}

View File

@ -250,10 +250,10 @@ public class UnimplementedServiceGrpc {
synchronized (UnimplementedServiceGrpc.class) {
result = serviceDescriptor;
if (result == null) {
serviceDescriptor = result = new io.grpc.ServiceDescriptor(
SERVICE_NAME,
new UnimplementedServiceDescriptorSupplier(),
METHOD_UNIMPLEMENTED_CALL);
serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME)
.setSchemaDescriptor(new UnimplementedServiceDescriptorSupplier())
.addMethod(METHOD_UNIMPLEMENTED_CALL)
.build();
}
}
}