diff --git a/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceImpl.java b/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceImpl.java index 8b82da2607..38f0ed2262 100644 --- a/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceImpl.java +++ b/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceImpl.java @@ -79,7 +79,7 @@ public class TestServiceImpl implements TestServiceGrpc.TestService { @Override public void emptyCall(EmptyProtos.Empty empty, - StreamObserver responseObserver) { + StreamObserver responseObserver) { responseObserver.onNext(EmptyProtos.Empty.getDefaultInstance()); responseObserver.onCompleted(); } diff --git a/services/build.gradle b/services/build.gradle new file mode 100644 index 0000000000..46479e7bfc --- /dev/null +++ b/services/build.gradle @@ -0,0 +1,35 @@ +// Add dependency on the protobuf plugin +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath libraries.protobuf_plugin + } +} + +plugins { + id "be.insaneprogramming.gradle.animalsniffer" version "1.4.0" +} + +description = "gRPC: Services" + +dependencies { + compile project(':grpc-protobuf'), + project(':grpc-stub') +} + +configureProtoCompilation() + +// Configure the animal sniffer plugin +animalsniffer { + signature = "org.codehaus.mojo.signature:java16:+@signature" +} + +// Let intellij projects refer to generated code +idea { + module { + sourceDirs += file("${projectDir}/src/generated/main/java"); + sourceDirs += file("${projectDir}/src/generated/main/grpc"); + } +} diff --git a/services/src/generated/main/grpc/io/grpc/health/v1/HealthGrpc.java b/services/src/generated/main/grpc/io/grpc/health/v1/HealthGrpc.java new file mode 100644 index 0000000000..0cb251f236 --- /dev/null +++ b/services/src/generated/main/grpc/io/grpc/health/v1/HealthGrpc.java @@ -0,0 +1,231 @@ +package io.grpc.health.v1; + +import static io.grpc.stub.ClientCalls.asyncUnaryCall; +import static io.grpc.stub.ClientCalls.asyncServerStreamingCall; +import static io.grpc.stub.ClientCalls.asyncClientStreamingCall; +import static io.grpc.stub.ClientCalls.asyncBidiStreamingCall; +import static io.grpc.stub.ClientCalls.blockingUnaryCall; +import static io.grpc.stub.ClientCalls.blockingServerStreamingCall; +import static io.grpc.stub.ClientCalls.futureUnaryCall; +import static io.grpc.MethodDescriptor.generateFullMethodName; +import static io.grpc.stub.ServerCalls.asyncUnaryCall; +import static io.grpc.stub.ServerCalls.asyncServerStreamingCall; +import static io.grpc.stub.ServerCalls.asyncClientStreamingCall; +import static io.grpc.stub.ServerCalls.asyncBidiStreamingCall; +import static io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall; +import static io.grpc.stub.ServerCalls.asyncUnimplementedStreamingCall; + +/** + */ +@javax.annotation.Generated( + value = "by gRPC proto compiler (version 0.15.0-SNAPSHOT)", + comments = "Source: health.proto") +public class HealthGrpc { + + private HealthGrpc() {} + + public static final String SERVICE_NAME = "grpc.health.v1.Health"; + + // Static method descriptors that strictly reflect the proto. + @io.grpc.ExperimentalApi + public static final io.grpc.MethodDescriptor METHOD_CHECK = + io.grpc.MethodDescriptor.create( + io.grpc.MethodDescriptor.MethodType.UNARY, + generateFullMethodName( + "grpc.health.v1.Health", "Check"), + io.grpc.protobuf.ProtoUtils.marshaller(io.grpc.health.v1.HealthCheckRequest.getDefaultInstance()), + io.grpc.protobuf.ProtoUtils.marshaller(io.grpc.health.v1.HealthCheckResponse.getDefaultInstance())); + + /** + * Creates a new async stub that supports all call types for the service + */ + public static HealthStub newStub(io.grpc.Channel channel) { + return new HealthStub(channel); + } + + /** + * Creates a new blocking-style stub that supports unary and streaming output calls on the service + */ + public static HealthBlockingStub newBlockingStub( + io.grpc.Channel channel) { + return new HealthBlockingStub(channel); + } + + /** + * Creates a new ListenableFuture-style stub that supports unary and streaming output calls on the service + */ + public static HealthFutureStub newFutureStub( + io.grpc.Channel channel) { + return new HealthFutureStub(channel); + } + + /** + */ + public static interface Health { + + /** + */ + public void check(io.grpc.health.v1.HealthCheckRequest request, + io.grpc.stub.StreamObserver responseObserver); + } + + @io.grpc.ExperimentalApi + public static abstract class AbstractHealth implements Health, io.grpc.BindableService { + + @java.lang.Override + public void check(io.grpc.health.v1.HealthCheckRequest request, + io.grpc.stub.StreamObserver responseObserver) { + asyncUnimplementedUnaryCall(METHOD_CHECK, responseObserver); + } + + @java.lang.Override public io.grpc.ServerServiceDefinition bindService() { + return HealthGrpc.bindService(this); + } + } + + /** + */ + public static interface HealthBlockingClient { + + /** + */ + public io.grpc.health.v1.HealthCheckResponse check(io.grpc.health.v1.HealthCheckRequest request); + } + + /** + */ + public static interface HealthFutureClient { + + /** + */ + public com.google.common.util.concurrent.ListenableFuture check( + io.grpc.health.v1.HealthCheckRequest request); + } + + public static class HealthStub extends io.grpc.stub.AbstractStub + implements Health { + private HealthStub(io.grpc.Channel channel) { + super(channel); + } + + private HealthStub(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected HealthStub build(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + return new HealthStub(channel, callOptions); + } + + @java.lang.Override + public void check(io.grpc.health.v1.HealthCheckRequest request, + io.grpc.stub.StreamObserver responseObserver) { + asyncUnaryCall( + getChannel().newCall(METHOD_CHECK, getCallOptions()), request, responseObserver); + } + } + + public static class HealthBlockingStub extends io.grpc.stub.AbstractStub + implements HealthBlockingClient { + private HealthBlockingStub(io.grpc.Channel channel) { + super(channel); + } + + private HealthBlockingStub(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected HealthBlockingStub build(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + return new HealthBlockingStub(channel, callOptions); + } + + @java.lang.Override + public io.grpc.health.v1.HealthCheckResponse check(io.grpc.health.v1.HealthCheckRequest request) { + return blockingUnaryCall( + getChannel(), METHOD_CHECK, getCallOptions(), request); + } + } + + public static class HealthFutureStub extends io.grpc.stub.AbstractStub + implements HealthFutureClient { + private HealthFutureStub(io.grpc.Channel channel) { + super(channel); + } + + private HealthFutureStub(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected HealthFutureStub build(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + return new HealthFutureStub(channel, callOptions); + } + + @java.lang.Override + public com.google.common.util.concurrent.ListenableFuture check( + io.grpc.health.v1.HealthCheckRequest request) { + return futureUnaryCall( + getChannel().newCall(METHOD_CHECK, getCallOptions()), request); + } + } + + private static final int METHODID_CHECK = 0; + + private static class MethodHandlers implements + io.grpc.stub.ServerCalls.UnaryMethod, + io.grpc.stub.ServerCalls.ServerStreamingMethod, + io.grpc.stub.ServerCalls.ClientStreamingMethod, + io.grpc.stub.ServerCalls.BidiStreamingMethod { + private final Health serviceImpl; + private final int methodId; + + public MethodHandlers(Health serviceImpl, int methodId) { + this.serviceImpl = serviceImpl; + this.methodId = methodId; + } + + @java.lang.Override + @java.lang.SuppressWarnings("unchecked") + public void invoke(Req request, io.grpc.stub.StreamObserver responseObserver) { + switch (methodId) { + case METHODID_CHECK: + serviceImpl.check((io.grpc.health.v1.HealthCheckRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; + default: + throw new AssertionError(); + } + } + + @java.lang.Override + @java.lang.SuppressWarnings("unchecked") + public io.grpc.stub.StreamObserver invoke( + io.grpc.stub.StreamObserver responseObserver) { + switch (methodId) { + default: + throw new AssertionError(); + } + } + } + + public static io.grpc.ServerServiceDefinition bindService( + final Health serviceImpl) { + return io.grpc.ServerServiceDefinition.builder(SERVICE_NAME) + .addMethod( + METHOD_CHECK, + asyncUnaryCall( + new MethodHandlers< + io.grpc.health.v1.HealthCheckRequest, + io.grpc.health.v1.HealthCheckResponse>( + serviceImpl, METHODID_CHECK))) + .build(); + } +} diff --git a/services/src/generated/main/java/io/grpc/health/v1/HealthCheckRequest.java b/services/src/generated/main/java/io/grpc/health/v1/HealthCheckRequest.java new file mode 100644 index 0000000000..b06ac1b991 --- /dev/null +++ b/services/src/generated/main/java/io/grpc/health/v1/HealthCheckRequest.java @@ -0,0 +1,440 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: health.proto + +package io.grpc.health.v1; + +/** + * Protobuf type {@code grpc.health.v1.HealthCheckRequest} + */ +public final class HealthCheckRequest extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:grpc.health.v1.HealthCheckRequest) + HealthCheckRequestOrBuilder { + // Use HealthCheckRequest.newBuilder() to construct. + private HealthCheckRequest(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private HealthCheckRequest() { + service_ = ""; + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); + } + private HealthCheckRequest( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) { + this(); + int mutable_bitField0_ = 0; + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!input.skipField(tag)) { + done = true; + } + break; + } + case 10: { + java.lang.String s = input.readStringRequireUtf8(); + + service_ = s; + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw new RuntimeException(e.setUnfinishedMessage(this)); + } catch (java.io.IOException e) { + throw new RuntimeException( + new com.google.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this)); + } finally { + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return io.grpc.health.v1.HealthProto.internal_static_grpc_health_v1_HealthCheckRequest_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return io.grpc.health.v1.HealthProto.internal_static_grpc_health_v1_HealthCheckRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + io.grpc.health.v1.HealthCheckRequest.class, io.grpc.health.v1.HealthCheckRequest.Builder.class); + } + + public static final int SERVICE_FIELD_NUMBER = 1; + private volatile java.lang.Object service_; + /** + * optional string service = 1; + */ + public java.lang.String getService() { + java.lang.Object ref = service_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + service_ = s; + return s; + } + } + /** + * optional string service = 1; + */ + public com.google.protobuf.ByteString + getServiceBytes() { + java.lang.Object ref = service_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + service_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!getServiceBytes().isEmpty()) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, service_); + } + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!getServiceBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, service_); + } + memoizedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + public static io.grpc.health.v1.HealthCheckRequest parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static io.grpc.health.v1.HealthCheckRequest parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static io.grpc.health.v1.HealthCheckRequest parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static io.grpc.health.v1.HealthCheckRequest parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static io.grpc.health.v1.HealthCheckRequest parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static io.grpc.health.v1.HealthCheckRequest parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static io.grpc.health.v1.HealthCheckRequest parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static io.grpc.health.v1.HealthCheckRequest parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static io.grpc.health.v1.HealthCheckRequest parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static io.grpc.health.v1.HealthCheckRequest parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(io.grpc.health.v1.HealthCheckRequest prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code grpc.health.v1.HealthCheckRequest} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:grpc.health.v1.HealthCheckRequest) + io.grpc.health.v1.HealthCheckRequestOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return io.grpc.health.v1.HealthProto.internal_static_grpc_health_v1_HealthCheckRequest_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return io.grpc.health.v1.HealthProto.internal_static_grpc_health_v1_HealthCheckRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + io.grpc.health.v1.HealthCheckRequest.class, io.grpc.health.v1.HealthCheckRequest.Builder.class); + } + + // Construct using io.grpc.health.v1.HealthCheckRequest.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + } + } + public Builder clear() { + super.clear(); + service_ = ""; + + return this; + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return io.grpc.health.v1.HealthProto.internal_static_grpc_health_v1_HealthCheckRequest_descriptor; + } + + public io.grpc.health.v1.HealthCheckRequest getDefaultInstanceForType() { + return io.grpc.health.v1.HealthCheckRequest.getDefaultInstance(); + } + + public io.grpc.health.v1.HealthCheckRequest build() { + io.grpc.health.v1.HealthCheckRequest result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public io.grpc.health.v1.HealthCheckRequest buildPartial() { + io.grpc.health.v1.HealthCheckRequest result = new io.grpc.health.v1.HealthCheckRequest(this); + result.service_ = service_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof io.grpc.health.v1.HealthCheckRequest) { + return mergeFrom((io.grpc.health.v1.HealthCheckRequest)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(io.grpc.health.v1.HealthCheckRequest other) { + if (other == io.grpc.health.v1.HealthCheckRequest.getDefaultInstance()) return this; + if (!other.getService().isEmpty()) { + service_ = other.service_; + onChanged(); + } + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + io.grpc.health.v1.HealthCheckRequest parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (io.grpc.health.v1.HealthCheckRequest) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private java.lang.Object service_ = ""; + /** + * optional string service = 1; + */ + public java.lang.String getService() { + java.lang.Object ref = service_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + service_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * optional string service = 1; + */ + public com.google.protobuf.ByteString + getServiceBytes() { + java.lang.Object ref = service_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + service_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * optional string service = 1; + */ + public Builder setService( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + service_ = value; + onChanged(); + return this; + } + /** + * optional string service = 1; + */ + public Builder clearService() { + + service_ = getDefaultInstance().getService(); + onChanged(); + return this; + } + /** + * optional string service = 1; + */ + public Builder setServiceBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + service_ = value; + onChanged(); + return this; + } + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return this; + } + + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return this; + } + + + // @@protoc_insertion_point(builder_scope:grpc.health.v1.HealthCheckRequest) + } + + // @@protoc_insertion_point(class_scope:grpc.health.v1.HealthCheckRequest) + private static final io.grpc.health.v1.HealthCheckRequest DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new io.grpc.health.v1.HealthCheckRequest(); + } + + public static io.grpc.health.v1.HealthCheckRequest getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + public HealthCheckRequest parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + try { + return new HealthCheckRequest(input, extensionRegistry); + } catch (RuntimeException e) { + if (e.getCause() instanceof + com.google.protobuf.InvalidProtocolBufferException) { + throw (com.google.protobuf.InvalidProtocolBufferException) + e.getCause(); + } + throw e; + } + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public io.grpc.health.v1.HealthCheckRequest getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/services/src/generated/main/java/io/grpc/health/v1/HealthCheckRequestOrBuilder.java b/services/src/generated/main/java/io/grpc/health/v1/HealthCheckRequestOrBuilder.java new file mode 100644 index 0000000000..ba9024bed1 --- /dev/null +++ b/services/src/generated/main/java/io/grpc/health/v1/HealthCheckRequestOrBuilder.java @@ -0,0 +1,19 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: health.proto + +package io.grpc.health.v1; + +public interface HealthCheckRequestOrBuilder extends + // @@protoc_insertion_point(interface_extends:grpc.health.v1.HealthCheckRequest) + com.google.protobuf.MessageOrBuilder { + + /** + * optional string service = 1; + */ + java.lang.String getService(); + /** + * optional string service = 1; + */ + com.google.protobuf.ByteString + getServiceBytes(); +} diff --git a/services/src/generated/main/java/io/grpc/health/v1/HealthCheckResponse.java b/services/src/generated/main/java/io/grpc/health/v1/HealthCheckResponse.java new file mode 100644 index 0000000000..2f945916ae --- /dev/null +++ b/services/src/generated/main/java/io/grpc/health/v1/HealthCheckResponse.java @@ -0,0 +1,498 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: health.proto + +package io.grpc.health.v1; + +/** + * Protobuf type {@code grpc.health.v1.HealthCheckResponse} + */ +public final class HealthCheckResponse extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:grpc.health.v1.HealthCheckResponse) + HealthCheckResponseOrBuilder { + // Use HealthCheckResponse.newBuilder() to construct. + private HealthCheckResponse(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private HealthCheckResponse() { + status_ = 0; + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); + } + private HealthCheckResponse( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) { + this(); + int mutable_bitField0_ = 0; + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!input.skipField(tag)) { + done = true; + } + break; + } + case 8: { + int rawValue = input.readEnum(); + + status_ = rawValue; + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw new RuntimeException(e.setUnfinishedMessage(this)); + } catch (java.io.IOException e) { + throw new RuntimeException( + new com.google.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this)); + } finally { + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return io.grpc.health.v1.HealthProto.internal_static_grpc_health_v1_HealthCheckResponse_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return io.grpc.health.v1.HealthProto.internal_static_grpc_health_v1_HealthCheckResponse_fieldAccessorTable + .ensureFieldAccessorsInitialized( + io.grpc.health.v1.HealthCheckResponse.class, io.grpc.health.v1.HealthCheckResponse.Builder.class); + } + + /** + * Protobuf enum {@code grpc.health.v1.HealthCheckResponse.ServingStatus} + */ + public enum ServingStatus + implements com.google.protobuf.ProtocolMessageEnum { + /** + * UNKNOWN = 0; + */ + UNKNOWN(0, 0), + /** + * SERVING = 1; + */ + SERVING(1, 1), + /** + * NOT_SERVING = 2; + */ + NOT_SERVING(2, 2), + UNRECOGNIZED(-1, -1), + ; + + /** + * UNKNOWN = 0; + */ + public static final int UNKNOWN_VALUE = 0; + /** + * SERVING = 1; + */ + public static final int SERVING_VALUE = 1; + /** + * NOT_SERVING = 2; + */ + public static final int NOT_SERVING_VALUE = 2; + + + public final int getNumber() { + if (index == -1) { + throw new java.lang.IllegalArgumentException( + "Can't get the number of an unknown enum value."); + } + return value; + } + + public static ServingStatus valueOf(int value) { + switch (value) { + case 0: return UNKNOWN; + case 1: return SERVING; + case 2: return NOT_SERVING; + default: return null; + } + } + + public static com.google.protobuf.Internal.EnumLiteMap + internalGetValueMap() { + return internalValueMap; + } + private static final com.google.protobuf.Internal.EnumLiteMap< + ServingStatus> internalValueMap = + new com.google.protobuf.Internal.EnumLiteMap() { + public ServingStatus findValueByNumber(int number) { + return ServingStatus.valueOf(number); + } + }; + + public final com.google.protobuf.Descriptors.EnumValueDescriptor + getValueDescriptor() { + return getDescriptor().getValues().get(index); + } + public final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptorForType() { + return getDescriptor(); + } + public static final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptor() { + return io.grpc.health.v1.HealthCheckResponse.getDescriptor().getEnumTypes().get(0); + } + + private static final ServingStatus[] VALUES = values(); + + public static ServingStatus valueOf( + com.google.protobuf.Descriptors.EnumValueDescriptor desc) { + if (desc.getType() != getDescriptor()) { + throw new java.lang.IllegalArgumentException( + "EnumValueDescriptor is not for this type."); + } + if (desc.getIndex() == -1) { + return UNRECOGNIZED; + } + return VALUES[desc.getIndex()]; + } + + private final int index; + private final int value; + + private ServingStatus(int index, int value) { + this.index = index; + this.value = value; + } + + // @@protoc_insertion_point(enum_scope:grpc.health.v1.HealthCheckResponse.ServingStatus) + } + + public static final int STATUS_FIELD_NUMBER = 1; + private int status_; + /** + * optional .grpc.health.v1.HealthCheckResponse.ServingStatus status = 1; + */ + public int getStatusValue() { + return status_; + } + /** + * optional .grpc.health.v1.HealthCheckResponse.ServingStatus status = 1; + */ + public io.grpc.health.v1.HealthCheckResponse.ServingStatus getStatus() { + io.grpc.health.v1.HealthCheckResponse.ServingStatus result = io.grpc.health.v1.HealthCheckResponse.ServingStatus.valueOf(status_); + return result == null ? io.grpc.health.v1.HealthCheckResponse.ServingStatus.UNRECOGNIZED : result; + } + + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (status_ != io.grpc.health.v1.HealthCheckResponse.ServingStatus.UNKNOWN.getNumber()) { + output.writeEnum(1, status_); + } + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (status_ != io.grpc.health.v1.HealthCheckResponse.ServingStatus.UNKNOWN.getNumber()) { + size += com.google.protobuf.CodedOutputStream + .computeEnumSize(1, status_); + } + memoizedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + public static io.grpc.health.v1.HealthCheckResponse parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static io.grpc.health.v1.HealthCheckResponse parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static io.grpc.health.v1.HealthCheckResponse parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static io.grpc.health.v1.HealthCheckResponse parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static io.grpc.health.v1.HealthCheckResponse parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static io.grpc.health.v1.HealthCheckResponse parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static io.grpc.health.v1.HealthCheckResponse parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static io.grpc.health.v1.HealthCheckResponse parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static io.grpc.health.v1.HealthCheckResponse parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static io.grpc.health.v1.HealthCheckResponse parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(io.grpc.health.v1.HealthCheckResponse prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code grpc.health.v1.HealthCheckResponse} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:grpc.health.v1.HealthCheckResponse) + io.grpc.health.v1.HealthCheckResponseOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return io.grpc.health.v1.HealthProto.internal_static_grpc_health_v1_HealthCheckResponse_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return io.grpc.health.v1.HealthProto.internal_static_grpc_health_v1_HealthCheckResponse_fieldAccessorTable + .ensureFieldAccessorsInitialized( + io.grpc.health.v1.HealthCheckResponse.class, io.grpc.health.v1.HealthCheckResponse.Builder.class); + } + + // Construct using io.grpc.health.v1.HealthCheckResponse.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + } + } + public Builder clear() { + super.clear(); + status_ = 0; + + return this; + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return io.grpc.health.v1.HealthProto.internal_static_grpc_health_v1_HealthCheckResponse_descriptor; + } + + public io.grpc.health.v1.HealthCheckResponse getDefaultInstanceForType() { + return io.grpc.health.v1.HealthCheckResponse.getDefaultInstance(); + } + + public io.grpc.health.v1.HealthCheckResponse build() { + io.grpc.health.v1.HealthCheckResponse result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public io.grpc.health.v1.HealthCheckResponse buildPartial() { + io.grpc.health.v1.HealthCheckResponse result = new io.grpc.health.v1.HealthCheckResponse(this); + result.status_ = status_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof io.grpc.health.v1.HealthCheckResponse) { + return mergeFrom((io.grpc.health.v1.HealthCheckResponse)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(io.grpc.health.v1.HealthCheckResponse other) { + if (other == io.grpc.health.v1.HealthCheckResponse.getDefaultInstance()) return this; + if (other.status_ != 0) { + setStatusValue(other.getStatusValue()); + } + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + io.grpc.health.v1.HealthCheckResponse parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (io.grpc.health.v1.HealthCheckResponse) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private int status_ = 0; + /** + * optional .grpc.health.v1.HealthCheckResponse.ServingStatus status = 1; + */ + public int getStatusValue() { + return status_; + } + /** + * optional .grpc.health.v1.HealthCheckResponse.ServingStatus status = 1; + */ + public Builder setStatusValue(int value) { + status_ = value; + onChanged(); + return this; + } + /** + * optional .grpc.health.v1.HealthCheckResponse.ServingStatus status = 1; + */ + public io.grpc.health.v1.HealthCheckResponse.ServingStatus getStatus() { + io.grpc.health.v1.HealthCheckResponse.ServingStatus result = io.grpc.health.v1.HealthCheckResponse.ServingStatus.valueOf(status_); + return result == null ? io.grpc.health.v1.HealthCheckResponse.ServingStatus.UNRECOGNIZED : result; + } + /** + * optional .grpc.health.v1.HealthCheckResponse.ServingStatus status = 1; + */ + public Builder setStatus(io.grpc.health.v1.HealthCheckResponse.ServingStatus value) { + if (value == null) { + throw new NullPointerException(); + } + + status_ = value.getNumber(); + onChanged(); + return this; + } + /** + * optional .grpc.health.v1.HealthCheckResponse.ServingStatus status = 1; + */ + public Builder clearStatus() { + + status_ = 0; + onChanged(); + return this; + } + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return this; + } + + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return this; + } + + + // @@protoc_insertion_point(builder_scope:grpc.health.v1.HealthCheckResponse) + } + + // @@protoc_insertion_point(class_scope:grpc.health.v1.HealthCheckResponse) + private static final io.grpc.health.v1.HealthCheckResponse DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new io.grpc.health.v1.HealthCheckResponse(); + } + + public static io.grpc.health.v1.HealthCheckResponse getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + public HealthCheckResponse parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + try { + return new HealthCheckResponse(input, extensionRegistry); + } catch (RuntimeException e) { + if (e.getCause() instanceof + com.google.protobuf.InvalidProtocolBufferException) { + throw (com.google.protobuf.InvalidProtocolBufferException) + e.getCause(); + } + throw e; + } + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public io.grpc.health.v1.HealthCheckResponse getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/services/src/generated/main/java/io/grpc/health/v1/HealthCheckResponseOrBuilder.java b/services/src/generated/main/java/io/grpc/health/v1/HealthCheckResponseOrBuilder.java new file mode 100644 index 0000000000..4d632bcd02 --- /dev/null +++ b/services/src/generated/main/java/io/grpc/health/v1/HealthCheckResponseOrBuilder.java @@ -0,0 +1,18 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: health.proto + +package io.grpc.health.v1; + +public interface HealthCheckResponseOrBuilder extends + // @@protoc_insertion_point(interface_extends:grpc.health.v1.HealthCheckResponse) + com.google.protobuf.MessageOrBuilder { + + /** + * optional .grpc.health.v1.HealthCheckResponse.ServingStatus status = 1; + */ + int getStatusValue(); + /** + * optional .grpc.health.v1.HealthCheckResponse.ServingStatus status = 1; + */ + io.grpc.health.v1.HealthCheckResponse.ServingStatus getStatus(); +} diff --git a/services/src/generated/main/java/io/grpc/health/v1/HealthProto.java b/services/src/generated/main/java/io/grpc/health/v1/HealthProto.java new file mode 100644 index 0000000000..31f1e78f00 --- /dev/null +++ b/services/src/generated/main/java/io/grpc/health/v1/HealthProto.java @@ -0,0 +1,68 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: health.proto + +package io.grpc.health.v1; + +public final class HealthProto { + private HealthProto() {} + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistry registry) { + } + static com.google.protobuf.Descriptors.Descriptor + internal_static_grpc_health_v1_HealthCheckRequest_descriptor; + static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_grpc_health_v1_HealthCheckRequest_fieldAccessorTable; + static com.google.protobuf.Descriptors.Descriptor + internal_static_grpc_health_v1_HealthCheckResponse_descriptor; + static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_grpc_health_v1_HealthCheckResponse_fieldAccessorTable; + + public static com.google.protobuf.Descriptors.FileDescriptor + getDescriptor() { + return descriptor; + } + private static com.google.protobuf.Descriptors.FileDescriptor + descriptor; + static { + java.lang.String[] descriptorData = { + "\n\014health.proto\022\016grpc.health.v1\"%\n\022Health" + + "CheckRequest\022\017\n\007service\030\001 \001(\t\"\224\001\n\023Health" + + "CheckResponse\022A\n\006status\030\001 \001(\01621.grpc.hea" + + "lth.v1.HealthCheckResponse.ServingStatus" + + "\":\n\rServingStatus\022\013\n\007UNKNOWN\020\000\022\013\n\007SERVIN" + + "G\020\001\022\017\n\013NOT_SERVING\020\0022Z\n\006Health\022P\n\005Check\022" + + "\".grpc.health.v1.HealthCheckRequest\032#.gr" + + "pc.health.v1.HealthCheckResponseB3\n\021io.g" + + "rpc.health.v1B\013HealthProtoP\001\252\002\016Grpc.Heal" + + "th.V1b\006proto3" + }; + com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = + new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() { + public com.google.protobuf.ExtensionRegistry assignDescriptors( + com.google.protobuf.Descriptors.FileDescriptor root) { + descriptor = root; + return null; + } + }; + com.google.protobuf.Descriptors.FileDescriptor + .internalBuildGeneratedFileFrom(descriptorData, + new com.google.protobuf.Descriptors.FileDescriptor[] { + }, assigner); + internal_static_grpc_health_v1_HealthCheckRequest_descriptor = + getDescriptor().getMessageTypes().get(0); + internal_static_grpc_health_v1_HealthCheckRequest_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_grpc_health_v1_HealthCheckRequest_descriptor, + new java.lang.String[] { "Service", }); + internal_static_grpc_health_v1_HealthCheckResponse_descriptor = + getDescriptor().getMessageTypes().get(1); + internal_static_grpc_health_v1_HealthCheckResponse_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_grpc_health_v1_HealthCheckResponse_descriptor, + new java.lang.String[] { "Status", }); + } + + // @@protoc_insertion_point(outer_class_scope) +} diff --git a/services/src/main/java/io/grpc/services/HealthServiceImpl.java b/services/src/main/java/io/grpc/services/HealthServiceImpl.java new file mode 100644 index 0000000000..6f6ce88670 --- /dev/null +++ b/services/src/main/java/io/grpc/services/HealthServiceImpl.java @@ -0,0 +1,86 @@ +/* + * Copyright 2016, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.grpc.services; + +import static io.grpc.health.v1.HealthCheckResponse.ServingStatus; + +import io.grpc.Status; +import io.grpc.StatusException; +import io.grpc.health.v1.HealthCheckRequest; +import io.grpc.health.v1.HealthCheckResponse; +import io.grpc.health.v1.HealthGrpc; +import io.grpc.stub.StreamObserver; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import javax.annotation.Nullable; + + +final class HealthServiceImpl extends HealthGrpc.AbstractHealth { + + /* Due to the latency of rpc calls, synchronization of the map does not help with consistency. + * However, need use ConcurrentHashMap to prevent the possible race condition of currently putting + * two keys with a colliding hashCode into the map. */ + private final Map statusMap + = new ConcurrentHashMap(); + + @Override + public void check(HealthCheckRequest request, + StreamObserver responseObserver) { + ServingStatus status = getStatus(request.getService()); + if (status == null) { + responseObserver.onError(new StatusException(Status.NOT_FOUND)); + } else { + HealthCheckResponse response = HealthCheckResponse.newBuilder().setStatus(status).build(); + responseObserver.onNext(response); + responseObserver.onCompleted(); + } + } + + void setStatus(String service, ServingStatus status) { + statusMap.put(service, status); + } + + @Nullable + ServingStatus getStatus(String service) { + return statusMap.get(service); + } + + void clearStatus(String service) { + statusMap.remove(service); + } + + void clearAll() { + statusMap.clear(); + } +} diff --git a/services/src/main/java/io/grpc/services/HealthStatusManager.java b/services/src/main/java/io/grpc/services/HealthStatusManager.java new file mode 100644 index 0000000000..620ab36cae --- /dev/null +++ b/services/src/main/java/io/grpc/services/HealthStatusManager.java @@ -0,0 +1,90 @@ +/* + * Copyright 2016, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.grpc.services; + +import static com.google.common.base.Preconditions.checkNotNull; +import static io.grpc.health.v1.HealthCheckResponse.ServingStatus; + +import io.grpc.health.v1.HealthGrpc; + + + +/** + * A {@code HealthStatusManager} object manages a health check service. A health check service is + * created in the constructor of {@code HealthStatusManager}, and it can be retrieved by the + * {@link #getHealthService()} method. + * The health status manager can update the health statuses of the server. + */ +@io.grpc.ExperimentalApi +public final class HealthStatusManager { + + private final HealthServiceImpl healthService; + + /** + * Creates a new health service instance. + */ + public HealthStatusManager() { + healthService = new HealthServiceImpl(); + } + + /** + * Gets the health check service created in the constructor. + */ + public HealthGrpc.AbstractHealth getHealthService() { + return healthService; + } + + /** + * Updates the status of the server. + * @param service the name of some aspect of the server that is associated with a health status. + * This name can have no relation with the gRPC services that the server is running with. + * It can also be an empty String {@code ""} per the gRPC specification. + * @param status is one of the values {@link ServingStatus#SERVING}, + * {@link ServingStatus#NOT_SERVING} and {@link ServingStatus#UNKNOWN}. + */ + public void setStatus(String service, ServingStatus status) { + checkNotNull(status, "status"); + healthService.setStatus(service, status); + } + + /** + * Clears the health status record of a service. The health service will respond with NOT_FOUND + * error on checking the status of a cleared service. + * @param service the name of some aspect of the server that is associated with a health status. + * This name can have no relation with the gRPC services that the server is running with. + * It can also be an empty String {@code ""} per the gRPC specification. + */ + public void clearStatus(String service) { + healthService.clearStatus(service); + } + +} diff --git a/services/src/main/java/io/grpc/services/package-info.java b/services/src/main/java/io/grpc/services/package-info.java new file mode 100644 index 0000000000..195e6aa2df --- /dev/null +++ b/services/src/main/java/io/grpc/services/package-info.java @@ -0,0 +1,35 @@ +/* + * Copyright 2016, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * Service definitions and utilities for the pre-defined gRPC services. + */ +package io.grpc.services; diff --git a/services/src/main/proto/health.proto b/services/src/main/proto/health.proto new file mode 100644 index 0000000000..bfe6a094d7 --- /dev/null +++ b/services/src/main/proto/health.proto @@ -0,0 +1,54 @@ +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package grpc.health.v1; +option csharp_namespace = "Grpc.Health.V1"; + +option java_multiple_files = true; +option java_package = "io.grpc.health.v1"; +option java_outer_classname = "HealthProto"; + +message HealthCheckRequest { + string service = 1; +} + +message HealthCheckResponse { + enum ServingStatus { + UNKNOWN = 0; + SERVING = 1; + NOT_SERVING = 2; + } + ServingStatus status = 1; +} + +service Health { + rpc Check(HealthCheckRequest) returns (HealthCheckResponse); +} diff --git a/services/src/test/java/io/grpc/services/HealthStatusManagerTest.java b/services/src/test/java/io/grpc/services/HealthStatusManagerTest.java new file mode 100644 index 0000000000..6e16eef609 --- /dev/null +++ b/services/src/test/java/io/grpc/services/HealthStatusManagerTest.java @@ -0,0 +1,131 @@ +/* + * Copyright 2016, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.grpc.services; + +import static io.grpc.health.v1.HealthGrpc.Health; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + + +import io.grpc.Status; +import io.grpc.StatusException; +import io.grpc.health.v1.HealthCheckRequest; +import io.grpc.health.v1.HealthCheckResponse; +import io.grpc.stub.StreamObserver; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.ArgumentCaptor; +import org.mockito.InOrder; + +/** Unit tests for {@link HealthStatusManager}. */ +@RunWith(JUnit4.class) +public class HealthStatusManagerTest { + + private final HealthStatusManager manager = new HealthStatusManager(); + private final Health health = manager.getHealthService(); + private final HealthCheckResponse.ServingStatus status + = HealthCheckResponse.ServingStatus.UNKNOWN; + + @Test + public void getHealthService_getterReturnsTheSameHealthRefAfterUpdate() throws Exception { + manager.setStatus("", status); + assertEquals(health, manager.getHealthService()); + } + + + @Test + public void checkValidStatus() throws Exception { + //setup + manager.setStatus("", status); + HealthCheckRequest request = HealthCheckRequest.newBuilder().setService("").build(); + @SuppressWarnings("unchecked") + StreamObserver observer = mock(StreamObserver.class); + + //test + health.check(request, observer); + + //verify + InOrder inOrder = inOrder(observer); + inOrder.verify(observer, times(1)).onNext(any(HealthCheckResponse.class)); + inOrder.verify(observer, times(1)).onCompleted(); + verify(observer, never()).onError(any(Throwable.class)); + } + + @Test + public void checkStatusNotFound() throws Exception { + //setup + manager.setStatus("", status); + HealthCheckRequest request + = HealthCheckRequest.newBuilder().setService("invalid").build(); + @SuppressWarnings("unchecked") + StreamObserver observer = mock(StreamObserver.class); + + //test + health.check(request, observer); + + //verify + ArgumentCaptor exception = ArgumentCaptor.forClass(StatusException.class); + verify(observer, times(1)).onError(exception.capture()); + assertEquals(Status.NOT_FOUND, exception.getValue().getStatus()); + + verify(observer, never()).onCompleted(); + } + + @Test + public void notFoundForClearedStatus() throws Exception { + //setup + manager.setStatus("", status); + manager.clearStatus(""); + HealthCheckRequest request + = HealthCheckRequest.newBuilder().setService("").build(); + @SuppressWarnings("unchecked") + StreamObserver observer = mock(StreamObserver.class); + + //test + health.check(request, observer); + + //verify + ArgumentCaptor exception = ArgumentCaptor.forClass(StatusException.class); + verify(observer, times(1)).onError(exception.capture()); + assertEquals(Status.NOT_FOUND, exception.getValue().getStatus()); + + verify(observer, never()).onCompleted(); + } +} diff --git a/settings.gradle b/settings.gradle index 9bed7a1075..8c199acb3b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -12,6 +12,7 @@ include ":grpc-testing" include ":grpc-interop-testing" include ":grpc-all" include ":grpc-benchmarks" +include ":grpc-services" include ":grpc-examples" project(':grpc-core').projectDir = "$rootDir/core" as File @@ -27,6 +28,7 @@ project(':grpc-testing').projectDir = "$rootDir/testing" as File project(':grpc-interop-testing').projectDir = "$rootDir/interop-testing" as File project(':grpc-all').projectDir = "$rootDir/all" as File project(':grpc-benchmarks').projectDir = "$rootDir/benchmarks" as File +project(':grpc-services').projectDir = "$rootDir/services" as File project(':grpc-examples').projectDir = "$rootDir/examples" as File if (settings.hasProperty('skipCodegen') && skipCodegen.toBoolean()) {