aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/csharp/Grpc.HealthCheck
diff options
context:
space:
mode:
authorGravatar Jan Tattermusch <jtattermusch@google.com>2015-07-14 20:29:21 -0700
committerGravatar Jan Tattermusch <jtattermusch@google.com>2015-07-15 10:29:57 -0700
commit5253467d5c41e3b2123cf894afdccf6340d225fb (patch)
treeb13dd29cd2a0ebf22695effeb9516a7222eeea5f /src/csharp/Grpc.HealthCheck
parente6d12d335c160b02a8f866775ffe953962f5988f (diff)
C# health checking support
Diffstat (limited to 'src/csharp/Grpc.HealthCheck')
-rw-r--r--src/csharp/Grpc.HealthCheck/.gitignore2
-rw-r--r--src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj74
-rw-r--r--src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec28
-rw-r--r--src/csharp/Grpc.HealthCheck/Health.cs687
-rw-r--r--src/csharp/Grpc.HealthCheck/HealthGrpc.cs78
-rw-r--r--src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs132
-rw-r--r--src/csharp/Grpc.HealthCheck/Properties/AssemblyInfo.cs12
-rw-r--r--src/csharp/Grpc.HealthCheck/packages.config5
-rw-r--r--src/csharp/Grpc.HealthCheck/proto/health.proto52
9 files changed, 1070 insertions, 0 deletions
diff --git a/src/csharp/Grpc.HealthCheck/.gitignore b/src/csharp/Grpc.HealthCheck/.gitignore
new file mode 100644
index 0000000000..1746e3269e
--- /dev/null
+++ b/src/csharp/Grpc.HealthCheck/.gitignore
@@ -0,0 +1,2 @@
+bin
+obj
diff --git a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj
new file mode 100644
index 0000000000..6d37b37deb
--- /dev/null
+++ b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{AA5E328A-8835-49D7-98ED-C29F2B3049F0}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Grpc.HealthCheck</RootNamespace>
+ <AssemblyName>Grpc.HealthCheck</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Google.ProtocolBuffers">
+ <HintPath>..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.dll</HintPath>
+ </Reference>
+ <Reference Include="Google.ProtocolBuffers.Serialization">
+ <HintPath>..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.Serialization.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Interactive.Async">
+ <HintPath>..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="HealthServiceImpl.cs" />
+ <Compile Include="Health.cs" />
+ <Compile Include="HealthGrpc.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ <None Include="proto\health.proto" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Grpc.Core\Grpc.Core.csproj">
+ <Project>{ccc4440e-49f7-4790-b0af-feabb0837ae7}</Project>
+ <Name>Grpc.Core</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec
new file mode 100644
index 0000000000..c774133ab0
--- /dev/null
+++ b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<package>
+ <metadata>
+ <id>Grpc.HealthCheck</id>
+ <title>gRPC C# Healthchecking</title>
+ <summary>Implementation of gRPC health service</summary>
+ <description>Example implementation of grpc.health.v1alpha service that can be used for health-checking.</description>
+ <version>0.6.0</version>
+ <authors>Google Inc.</authors>
+ <owners>grpc-packages</owners>
+ <licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
+ <projectUrl>https://github.com/grpc/grpc</projectUrl>
+ <requireLicenseAcceptance>false</requireLicenseAcceptance>
+ <copyright>Copyright 2015, Google Inc.</copyright>
+ <tags>gRPC health check</tags>
+ <dependencies>
+ <dependency id="Google.ProtocolBuffers" version="2.4.1.555" />
+ <dependency id="Grpc.Core" version="0.6.0" />
+ <dependency id="Ix-Async" version="1.2.3" />
+ </dependencies>
+ </metadata>
+ <files>
+ <file src="bin/Release/Grpc.HealthCheck.dll" target="lib/net45" />
+ <file src="bin/Release/Grpc.HealthCheck.pdb" target="lib/net45" />
+ <file src="bin/Release/Grpc.HealthCheck.xml" target="lib/net45" />
+ <file src="**\*.cs" target="src" />
+ </files>
+</package>
diff --git a/src/csharp/Grpc.HealthCheck/Health.cs b/src/csharp/Grpc.HealthCheck/Health.cs
new file mode 100644
index 0000000000..361382d4bd
--- /dev/null
+++ b/src/csharp/Grpc.HealthCheck/Health.cs
@@ -0,0 +1,687 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: health.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.ProtocolBuffers;
+using pbc = global::Google.ProtocolBuffers.Collections;
+using pbd = global::Google.ProtocolBuffers.Descriptors;
+using scg = global::System.Collections.Generic;
+namespace Grpc.Health.V1Alpha {
+
+ namespace Proto {
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public static partial class Health {
+
+ #region Extension registration
+ public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {
+ }
+ #endregion
+ #region Static variables
+ internal static pbd::MessageDescriptor internal__static_grpc_health_v1alpha_HealthCheckRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable<global::Grpc.Health.V1Alpha.HealthCheckRequest, global::Grpc.Health.V1Alpha.HealthCheckRequest.Builder> internal__static_grpc_health_v1alpha_HealthCheckRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_grpc_health_v1alpha_HealthCheckResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable<global::Grpc.Health.V1Alpha.HealthCheckResponse, global::Grpc.Health.V1Alpha.HealthCheckResponse.Builder> internal__static_grpc_health_v1alpha_HealthCheckResponse__FieldAccessorTable;
+ #endregion
+ #region Descriptor
+ public static pbd::FileDescriptor Descriptor {
+ get { return descriptor; }
+ }
+ private static pbd::FileDescriptor descriptor;
+
+ static Health() {
+ byte[] descriptorData = global::System.Convert.FromBase64String(
+ string.Concat(
+ "CgxoZWFsdGgucHJvdG8SE2dycGMuaGVhbHRoLnYxYWxwaGEiMwoSSGVhbHRo",
+ "Q2hlY2tSZXF1ZXN0EgwKBGhvc3QYASABKAkSDwoHc2VydmljZRgCIAEoCSKZ",
+ "AQoTSGVhbHRoQ2hlY2tSZXNwb25zZRJGCgZzdGF0dXMYASABKA4yNi5ncnBj",
+ "LmhlYWx0aC52MWFscGhhLkhlYWx0aENoZWNrUmVzcG9uc2UuU2VydmluZ1N0",
+ "YXR1cyI6Cg1TZXJ2aW5nU3RhdHVzEgsKB1VOS05PV04QABILCgdTRVJWSU5H",
+ "EAESDwoLTk9UX1NFUlZJTkcQAjJkCgZIZWFsdGgSWgoFQ2hlY2sSJy5ncnBj",
+ "LmhlYWx0aC52MWFscGhhLkhlYWx0aENoZWNrUmVxdWVzdBooLmdycGMuaGVh",
+ "bHRoLnYxYWxwaGEuSGVhbHRoQ2hlY2tSZXNwb25zZUIWqgITR3JwYy5IZWFs",
+ "dGguVjFBbHBoYQ=="));
+ pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
+ descriptor = root;
+ internal__static_grpc_health_v1alpha_HealthCheckRequest__Descriptor = Descriptor.MessageTypes[0];
+ internal__static_grpc_health_v1alpha_HealthCheckRequest__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable<global::Grpc.Health.V1Alpha.HealthCheckRequest, global::Grpc.Health.V1Alpha.HealthCheckRequest.Builder>(internal__static_grpc_health_v1alpha_HealthCheckRequest__Descriptor,
+ new string[] { "Host", "Service", });
+ internal__static_grpc_health_v1alpha_HealthCheckResponse__Descriptor = Descriptor.MessageTypes[1];
+ internal__static_grpc_health_v1alpha_HealthCheckResponse__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable<global::Grpc.Health.V1Alpha.HealthCheckResponse, global::Grpc.Health.V1Alpha.HealthCheckResponse.Builder>(internal__static_grpc_health_v1alpha_HealthCheckResponse__Descriptor,
+ new string[] { "Status", });
+ pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();
+ RegisterAllExtensions(registry);
+ return registry;
+ };
+ pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+ new pbd::FileDescriptor[] {
+ }, assigner);
+ }
+ #endregion
+
+ }
+ }
+ #region Messages
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class HealthCheckRequest : pb::GeneratedMessage<HealthCheckRequest, HealthCheckRequest.Builder> {
+ private HealthCheckRequest() { }
+ private static readonly HealthCheckRequest defaultInstance = new HealthCheckRequest().MakeReadOnly();
+ private static readonly string[] _healthCheckRequestFieldNames = new string[] { "host", "service" };
+ private static readonly uint[] _healthCheckRequestFieldTags = new uint[] { 10, 18 };
+ public static HealthCheckRequest DefaultInstance {
+ get { return defaultInstance; }
+ }
+
+ public override HealthCheckRequest DefaultInstanceForType {
+ get { return DefaultInstance; }
+ }
+
+ protected override HealthCheckRequest ThisMessage {
+ get { return this; }
+ }
+
+ public static pbd::MessageDescriptor Descriptor {
+ get { return global::Grpc.Health.V1Alpha.Proto.Health.internal__static_grpc_health_v1alpha_HealthCheckRequest__Descriptor; }
+ }
+
+ protected override pb::FieldAccess.FieldAccessorTable<HealthCheckRequest, HealthCheckRequest.Builder> InternalFieldAccessors {
+ get { return global::Grpc.Health.V1Alpha.Proto.Health.internal__static_grpc_health_v1alpha_HealthCheckRequest__FieldAccessorTable; }
+ }
+
+ public const int HostFieldNumber = 1;
+ private bool hasHost;
+ private string host_ = "";
+ public bool HasHost {
+ get { return hasHost; }
+ }
+ public string Host {
+ get { return host_; }
+ }
+
+ public const int ServiceFieldNumber = 2;
+ private bool hasService;
+ private string service_ = "";
+ public bool HasService {
+ get { return hasService; }
+ }
+ public string Service {
+ get { return service_; }
+ }
+
+ public override bool IsInitialized {
+ get {
+ return true;
+ }
+ }
+
+ public override void WriteTo(pb::ICodedOutputStream output) {
+ CalcSerializedSize();
+ string[] field_names = _healthCheckRequestFieldNames;
+ if (hasHost) {
+ output.WriteString(1, field_names[0], Host);
+ }
+ if (hasService) {
+ output.WriteString(2, field_names[1], Service);
+ }
+ UnknownFields.WriteTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public override int SerializedSize {
+ get {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+ return CalcSerializedSize();
+ }
+ }
+
+ private int CalcSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (hasHost) {
+ size += pb::CodedOutputStream.ComputeStringSize(1, Host);
+ }
+ if (hasService) {
+ size += pb::CodedOutputStream.ComputeStringSize(2, Service);
+ }
+ size += UnknownFields.SerializedSize;
+ memoizedSerializedSize = size;
+ return size;
+ }
+ public static HealthCheckRequest ParseFrom(pb::ByteString data) {
+ return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+ }
+ public static HealthCheckRequest ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+ }
+ public static HealthCheckRequest ParseFrom(byte[] data) {
+ return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+ }
+ public static HealthCheckRequest ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+ }
+ public static HealthCheckRequest ParseFrom(global::System.IO.Stream input) {
+ return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+ }
+ public static HealthCheckRequest ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+ }
+ public static HealthCheckRequest ParseDelimitedFrom(global::System.IO.Stream input) {
+ return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
+ }
+ public static HealthCheckRequest ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+ return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
+ }
+ public static HealthCheckRequest ParseFrom(pb::ICodedInputStream input) {
+ return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+ }
+ public static HealthCheckRequest ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+ }
+ private HealthCheckRequest MakeReadOnly() {
+ return this;
+ }
+
+ public static Builder CreateBuilder() { return new Builder(); }
+ public override Builder ToBuilder() { return CreateBuilder(this); }
+ public override Builder CreateBuilderForType() { return new Builder(); }
+ public static Builder CreateBuilder(HealthCheckRequest prototype) {
+ return new Builder(prototype);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class Builder : pb::GeneratedBuilder<HealthCheckRequest, Builder> {
+ protected override Builder ThisBuilder {
+ get { return this; }
+ }
+ public Builder() {
+ result = DefaultInstance;
+ resultIsReadOnly = true;
+ }
+ internal Builder(HealthCheckRequest cloneFrom) {
+ result = cloneFrom;
+ resultIsReadOnly = true;
+ }
+
+ private bool resultIsReadOnly;
+ private HealthCheckRequest result;
+
+ private HealthCheckRequest PrepareBuilder() {
+ if (resultIsReadOnly) {
+ HealthCheckRequest original = result;
+ result = new HealthCheckRequest();
+ resultIsReadOnly = false;
+ MergeFrom(original);
+ }
+ return result;
+ }
+
+ public override bool IsInitialized {
+ get { return result.IsInitialized; }
+ }
+
+ protected override HealthCheckRequest MessageBeingBuilt {
+ get { return PrepareBuilder(); }
+ }
+
+ public override Builder Clear() {
+ result = DefaultInstance;
+ resultIsReadOnly = true;
+ return this;
+ }
+
+ public override Builder Clone() {
+ if (resultIsReadOnly) {
+ return new Builder(result);
+ } else {
+ return new Builder().MergeFrom(result);
+ }
+ }
+
+ public override pbd::MessageDescriptor DescriptorForType {
+ get { return global::Grpc.Health.V1Alpha.HealthCheckRequest.Descriptor; }
+ }
+
+ public override HealthCheckRequest DefaultInstanceForType {
+ get { return global::Grpc.Health.V1Alpha.HealthCheckRequest.DefaultInstance; }
+ }
+
+ public override HealthCheckRequest BuildPartial() {
+ if (resultIsReadOnly) {
+ return result;
+ }
+ resultIsReadOnly = true;
+ return result.MakeReadOnly();
+ }
+
+ public override Builder MergeFrom(pb::IMessage other) {
+ if (other is HealthCheckRequest) {
+ return MergeFrom((HealthCheckRequest) other);
+ } else {
+ base.MergeFrom(other);
+ return this;
+ }
+ }
+
+ public override Builder MergeFrom(HealthCheckRequest other) {
+ if (other == global::Grpc.Health.V1Alpha.HealthCheckRequest.DefaultInstance) return this;
+ PrepareBuilder();
+ if (other.HasHost) {
+ Host = other.Host;
+ }
+ if (other.HasService) {
+ Service = other.Service;
+ }
+ this.MergeUnknownFields(other.UnknownFields);
+ return this;
+ }
+
+ public override Builder MergeFrom(pb::ICodedInputStream input) {
+ return MergeFrom(input, pb::ExtensionRegistry.Empty);
+ }
+
+ public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+ PrepareBuilder();
+ pb::UnknownFieldSet.Builder unknownFields = null;
+ uint tag;
+ string field_name;
+ while (input.ReadTag(out tag, out field_name)) {
+ if(tag == 0 && field_name != null) {
+ int field_ordinal = global::System.Array.BinarySearch(_healthCheckRequestFieldNames, field_name, global::System.StringComparer.Ordinal);
+ if(field_ordinal >= 0)
+ tag = _healthCheckRequestFieldTags[field_ordinal];
+ else {
+ if (unknownFields == null) {
+ unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+ }
+ ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+ continue;
+ }
+ }
+ switch (tag) {
+ case 0: {
+ throw pb::InvalidProtocolBufferException.InvalidTag();
+ }
+ default: {
+ if (pb::WireFormat.IsEndGroupTag(tag)) {
+ if (unknownFields != null) {
+ this.UnknownFields = unknownFields.Build();
+ }
+ return this;
+ }
+ if (unknownFields == null) {
+ unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+ }
+ ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+ break;
+ }
+ case 10: {
+ result.hasHost = input.ReadString(ref result.host_);
+ break;
+ }
+ case 18: {
+ result.hasService = input.ReadString(ref result.service_);
+ break;
+ }
+ }
+ }
+
+ if (unknownFields != null) {
+ this.UnknownFields = unknownFields.Build();
+ }
+ return this;
+ }
+
+
+ public bool HasHost {
+ get { return result.hasHost; }
+ }
+ public string Host {
+ get { return result.Host; }
+ set { SetHost(value); }
+ }
+ public Builder SetHost(string value) {
+ pb::ThrowHelper.ThrowIfNull(value, "value");
+ PrepareBuilder();
+ result.hasHost = true;
+ result.host_ = value;
+ return this;
+ }
+ public Builder ClearHost() {
+ PrepareBuilder();
+ result.hasHost = false;
+ result.host_ = "";
+ return this;
+ }
+
+ public bool HasService {
+ get { return result.hasService; }
+ }
+ public string Service {
+ get { return result.Service; }
+ set { SetService(value); }
+ }
+ public Builder SetService(string value) {
+ pb::ThrowHelper.ThrowIfNull(value, "value");
+ PrepareBuilder();
+ result.hasService = true;
+ result.service_ = value;
+ return this;
+ }
+ public Builder ClearService() {
+ PrepareBuilder();
+ result.hasService = false;
+ result.service_ = "";
+ return this;
+ }
+ }
+ static HealthCheckRequest() {
+ object.ReferenceEquals(global::Grpc.Health.V1Alpha.Proto.Health.Descriptor, null);
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class HealthCheckResponse : pb::GeneratedMessage<HealthCheckResponse, HealthCheckResponse.Builder> {
+ private HealthCheckResponse() { }
+ private static readonly HealthCheckResponse defaultInstance = new HealthCheckResponse().MakeReadOnly();
+ private static readonly string[] _healthCheckResponseFieldNames = new string[] { "status" };
+ private static readonly uint[] _healthCheckResponseFieldTags = new uint[] { 8 };
+ public static HealthCheckResponse DefaultInstance {
+ get { return defaultInstance; }
+ }
+
+ public override HealthCheckResponse DefaultInstanceForType {
+ get { return DefaultInstance; }
+ }
+
+ protected override HealthCheckResponse ThisMessage {
+ get { return this; }
+ }
+
+ public static pbd::MessageDescriptor Descriptor {
+ get { return global::Grpc.Health.V1Alpha.Proto.Health.internal__static_grpc_health_v1alpha_HealthCheckResponse__Descriptor; }
+ }
+
+ protected override pb::FieldAccess.FieldAccessorTable<HealthCheckResponse, HealthCheckResponse.Builder> InternalFieldAccessors {
+ get { return global::Grpc.Health.V1Alpha.Proto.Health.internal__static_grpc_health_v1alpha_HealthCheckResponse__FieldAccessorTable; }
+ }
+
+ #region Nested types
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public static partial class Types {
+ public enum ServingStatus {
+ UNKNOWN = 0,
+ SERVING = 1,
+ NOT_SERVING = 2,
+ }
+
+ }
+ #endregion
+
+ public const int StatusFieldNumber = 1;
+ private bool hasStatus;
+ private global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus status_ = global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus.UNKNOWN;
+ public bool HasStatus {
+ get { return hasStatus; }
+ }
+ public global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus Status {
+ get { return status_; }
+ }
+
+ public override bool IsInitialized {
+ get {
+ return true;
+ }
+ }
+
+ public override void WriteTo(pb::ICodedOutputStream output) {
+ CalcSerializedSize();
+ string[] field_names = _healthCheckResponseFieldNames;
+ if (hasStatus) {
+ output.WriteEnum(1, field_names[0], (int) Status, Status);
+ }
+ UnknownFields.WriteTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public override int SerializedSize {
+ get {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+ return CalcSerializedSize();
+ }
+ }
+
+ private int CalcSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (hasStatus) {
+ size += pb::CodedOutputStream.ComputeEnumSize(1, (int) Status);
+ }
+ size += UnknownFields.SerializedSize;
+ memoizedSerializedSize = size;
+ return size;
+ }
+ public static HealthCheckResponse ParseFrom(pb::ByteString data) {
+ return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+ }
+ public static HealthCheckResponse ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+ }
+ public static HealthCheckResponse ParseFrom(byte[] data) {
+ return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+ }
+ public static HealthCheckResponse ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+ }
+ public static HealthCheckResponse ParseFrom(global::System.IO.Stream input) {
+ return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+ }
+ public static HealthCheckResponse ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+ }
+ public static HealthCheckResponse ParseDelimitedFrom(global::System.IO.Stream input) {
+ return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
+ }
+ public static HealthCheckResponse ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+ return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
+ }
+ public static HealthCheckResponse ParseFrom(pb::ICodedInputStream input) {
+ return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+ }
+ public static HealthCheckResponse ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+ }
+ private HealthCheckResponse MakeReadOnly() {
+ return this;
+ }
+
+ public static Builder CreateBuilder() { return new Builder(); }
+ public override Builder ToBuilder() { return CreateBuilder(this); }
+ public override Builder CreateBuilderForType() { return new Builder(); }
+ public static Builder CreateBuilder(HealthCheckResponse prototype) {
+ return new Builder(prototype);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class Builder : pb::GeneratedBuilder<HealthCheckResponse, Builder> {
+ protected override Builder ThisBuilder {
+ get { return this; }
+ }
+ public Builder() {
+ result = DefaultInstance;
+ resultIsReadOnly = true;
+ }
+ internal Builder(HealthCheckResponse cloneFrom) {
+ result = cloneFrom;
+ resultIsReadOnly = true;
+ }
+
+ private bool resultIsReadOnly;
+ private HealthCheckResponse result;
+
+ private HealthCheckResponse PrepareBuilder() {
+ if (resultIsReadOnly) {
+ HealthCheckResponse original = result;
+ result = new HealthCheckResponse();
+ resultIsReadOnly = false;
+ MergeFrom(original);
+ }
+ return result;
+ }
+
+ public override bool IsInitialized {
+ get { return result.IsInitialized; }
+ }
+
+ protected override HealthCheckResponse MessageBeingBuilt {
+ get { return PrepareBuilder(); }
+ }
+
+ public override Builder Clear() {
+ result = DefaultInstance;
+ resultIsReadOnly = true;
+ return this;
+ }
+
+ public override Builder Clone() {
+ if (resultIsReadOnly) {
+ return new Builder(result);
+ } else {
+ return new Builder().MergeFrom(result);
+ }
+ }
+
+ public override pbd::MessageDescriptor DescriptorForType {
+ get { return global::Grpc.Health.V1Alpha.HealthCheckResponse.Descriptor; }
+ }
+
+ public override HealthCheckResponse DefaultInstanceForType {
+ get { return global::Grpc.Health.V1Alpha.HealthCheckResponse.DefaultInstance; }
+ }
+
+ public override HealthCheckResponse BuildPartial() {
+ if (resultIsReadOnly) {
+ return result;
+ }
+ resultIsReadOnly = true;
+ return result.MakeReadOnly();
+ }
+
+ public override Builder MergeFrom(pb::IMessage other) {
+ if (other is HealthCheckResponse) {
+ return MergeFrom((HealthCheckResponse) other);
+ } else {
+ base.MergeFrom(other);
+ return this;
+ }
+ }
+
+ public override Builder MergeFrom(HealthCheckResponse other) {
+ if (other == global::Grpc.Health.V1Alpha.HealthCheckResponse.DefaultInstance) return this;
+ PrepareBuilder();
+ if (other.HasStatus) {
+ Status = other.Status;
+ }
+ this.MergeUnknownFields(other.UnknownFields);
+ return this;
+ }
+
+ public override Builder MergeFrom(pb::ICodedInputStream input) {
+ return MergeFrom(input, pb::ExtensionRegistry.Empty);
+ }
+
+ public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+ PrepareBuilder();
+ pb::UnknownFieldSet.Builder unknownFields = null;
+ uint tag;
+ string field_name;
+ while (input.ReadTag(out tag, out field_name)) {
+ if(tag == 0 && field_name != null) {
+ int field_ordinal = global::System.Array.BinarySearch(_healthCheckResponseFieldNames, field_name, global::System.StringComparer.Ordinal);
+ if(field_ordinal >= 0)
+ tag = _healthCheckResponseFieldTags[field_ordinal];
+ else {
+ if (unknownFields == null) {
+ unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+ }
+ ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+ continue;
+ }
+ }
+ switch (tag) {
+ case 0: {
+ throw pb::InvalidProtocolBufferException.InvalidTag();
+ }
+ default: {
+ if (pb::WireFormat.IsEndGroupTag(tag)) {
+ if (unknownFields != null) {
+ this.UnknownFields = unknownFields.Build();
+ }
+ return this;
+ }
+ if (unknownFields == null) {
+ unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+ }
+ ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+ break;
+ }
+ case 8: {
+ object unknown;
+ if(input.ReadEnum(ref result.status_, out unknown)) {
+ result.hasStatus = true;
+ } else if(unknown is int) {
+ if (unknownFields == null) {
+ unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+ }
+ unknownFields.MergeVarintField(1, (ulong)(int)unknown);
+ }
+ break;
+ }
+ }
+ }
+
+ if (unknownFields != null) {
+ this.UnknownFields = unknownFields.Build();
+ }
+ return this;
+ }
+
+
+ public bool HasStatus {
+ get { return result.hasStatus; }
+ }
+ public global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus Status {
+ get { return result.Status; }
+ set { SetStatus(value); }
+ }
+ public Builder SetStatus(global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus value) {
+ PrepareBuilder();
+ result.hasStatus = true;
+ result.status_ = value;
+ return this;
+ }
+ public Builder ClearStatus() {
+ PrepareBuilder();
+ result.hasStatus = false;
+ result.status_ = global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus.UNKNOWN;
+ return this;
+ }
+ }
+ static HealthCheckResponse() {
+ object.ReferenceEquals(global::Grpc.Health.V1Alpha.Proto.Health.Descriptor, null);
+ }
+ }
+
+ #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs
new file mode 100644
index 0000000000..ed9fc4ed77
--- /dev/null
+++ b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs
@@ -0,0 +1,78 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: health.proto
+#region Designer generated code
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Grpc.Core;
+
+namespace Grpc.Health.V1Alpha {
+ public static class Health
+ {
+ static readonly string __ServiceName = "grpc.health.v1alpha.Health";
+
+ static readonly Marshaller<global::Grpc.Health.V1Alpha.HealthCheckRequest> __Marshaller_HealthCheckRequest = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Health.V1Alpha.HealthCheckRequest.ParseFrom);
+ static readonly Marshaller<global::Grpc.Health.V1Alpha.HealthCheckResponse> __Marshaller_HealthCheckResponse = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Health.V1Alpha.HealthCheckResponse.ParseFrom);
+
+ static readonly Method<global::Grpc.Health.V1Alpha.HealthCheckRequest, global::Grpc.Health.V1Alpha.HealthCheckResponse> __Method_Check = new Method<global::Grpc.Health.V1Alpha.HealthCheckRequest, global::Grpc.Health.V1Alpha.HealthCheckResponse>(
+ MethodType.Unary,
+ "Check",
+ __Marshaller_HealthCheckRequest,
+ __Marshaller_HealthCheckResponse);
+
+ // client-side stub interface
+ public interface IHealthClient
+ {
+ global::Grpc.Health.V1Alpha.HealthCheckResponse Check(global::Grpc.Health.V1Alpha.HealthCheckRequest request, CancellationToken token = default(CancellationToken));
+ Task<global::Grpc.Health.V1Alpha.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1Alpha.HealthCheckRequest request, CancellationToken token = default(CancellationToken));
+ }
+
+ // server-side interface
+ public interface IHealth
+ {
+ Task<global::Grpc.Health.V1Alpha.HealthCheckResponse> Check(ServerCallContext context, global::Grpc.Health.V1Alpha.HealthCheckRequest request);
+ }
+
+ // client stub
+ public class HealthClient : AbstractStub<HealthClient, StubConfiguration>, IHealthClient
+ {
+ public HealthClient(Channel channel) : this(channel, StubConfiguration.Default)
+ {
+ }
+ public HealthClient(Channel channel, StubConfiguration config) : base(channel, config)
+ {
+ }
+ public global::Grpc.Health.V1Alpha.HealthCheckResponse Check(global::Grpc.Health.V1Alpha.HealthCheckRequest request, CancellationToken token = default(CancellationToken))
+ {
+ var call = CreateCall(__ServiceName, __Method_Check);
+ return Calls.BlockingUnaryCall(call, request, token);
+ }
+ public Task<global::Grpc.Health.V1Alpha.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1Alpha.HealthCheckRequest request, CancellationToken token = default(CancellationToken))
+ {
+ var call = CreateCall(__ServiceName, __Method_Check);
+ return Calls.AsyncUnaryCall(call, request, token);
+ }
+ }
+
+ // creates service definition that can be registered with a server
+ public static ServerServiceDefinition BindService(IHealth serviceImpl)
+ {
+ return ServerServiceDefinition.CreateBuilder(__ServiceName)
+ .AddMethod(__Method_Check, serviceImpl.Check).Build();
+ }
+
+ // creates a new client stub
+ public static IHealthClient NewStub(Channel channel)
+ {
+ return new HealthClient(channel);
+ }
+
+ // creates a new client stub
+ public static IHealthClient NewStub(Channel channel, StubConfiguration config)
+ {
+ return new HealthClient(channel, config);
+ }
+ }
+}
+#endregion
diff --git a/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs b/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs
new file mode 100644
index 0000000000..db3a2a0942
--- /dev/null
+++ b/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs
@@ -0,0 +1,132 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Grpc.Core;
+using Grpc.Core.Utils;
+using Grpc.Health.V1Alpha;
+
+namespace Grpc.HealthCheck
+{
+ /// <summary>
+ /// Implementation of a simple Health service. Useful for health checking.
+ ///
+ /// Registering service with a server:
+ /// <code>
+ /// var serviceImpl = new HealthServiceImpl();
+ /// server = new Server();
+ /// server.AddServiceDefinition(Grpc.Health.V1Alpha.Health.BindService(serviceImpl));
+ /// </code>
+ /// </summary>
+ public class HealthServiceImpl : Grpc.Health.V1Alpha.Health.IHealth
+ {
+ private readonly object myLock = new object();
+ private readonly Dictionary<Key, HealthCheckResponse.Types.ServingStatus> statusMap =
+ new Dictionary<Key, HealthCheckResponse.Types.ServingStatus>();
+
+ /// <summary>
+ /// Sets the health status for given host and service.
+ /// </summary>
+ /// <param name="host">The host. Cannot be null.</param>
+ /// <param name="service">The service. Cannot be null.</param>
+ /// <param name="status">the health status</param>
+ public void SetStatus(string host, string service, HealthCheckResponse.Types.ServingStatus status)
+ {
+ lock (myLock)
+ {
+ statusMap[CreateKey(host, service)] = status;
+ }
+ }
+
+ /// <summary>
+ /// Clears health status for given host and service.
+ /// </summary>
+ /// <param name="host">The host. Cannot be null.</param>
+ /// <param name="service">The service. Cannot be null.</param>
+ public void ClearStatus(string host, string service)
+ {
+ lock (myLock)
+ {
+ statusMap.Remove(CreateKey(host, service));
+ }
+ }
+
+ /// <summary>
+ /// Clears statuses for all hosts and services.
+ /// </summary>
+ public void ClearAll()
+ {
+ lock (myLock)
+ {
+ statusMap.Clear();
+ }
+ }
+
+ public Task<HealthCheckResponse> Check(ServerCallContext context, HealthCheckRequest request)
+ {
+ lock (myLock)
+ {
+ var host = request.HasHost ? request.Host : "";
+ var service = request.HasService ? request.Service : "";
+
+ HealthCheckResponse.Types.ServingStatus status;
+ if (!statusMap.TryGetValue(CreateKey(host, service), out status))
+ {
+ // TODO(jtattermusch): returning specific status from server handler is not supported yet.
+ throw new RpcException(new Status(StatusCode.NotFound, ""));
+ }
+ return Task.FromResult(HealthCheckResponse.CreateBuilder().SetStatus(status).Build());
+ }
+ }
+
+ private static Key CreateKey(string host, string service)
+ {
+ return new Key(host, service);
+ }
+
+ private struct Key
+ {
+ public Key(string host, string service)
+ {
+ this.Host = Preconditions.CheckNotNull(host);
+ this.Service = Preconditions.CheckNotNull(service);
+ }
+
+ readonly string Host;
+ readonly string Service;
+ }
+ }
+}
diff --git a/src/csharp/Grpc.HealthCheck/Properties/AssemblyInfo.cs b/src/csharp/Grpc.HealthCheck/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..6cfdb7e6e2
--- /dev/null
+++ b/src/csharp/Grpc.HealthCheck/Properties/AssemblyInfo.cs
@@ -0,0 +1,12 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyTitle("Grpc.HealthCheck")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: AssemblyVersion("0.6.*")] \ No newline at end of file
diff --git a/src/csharp/Grpc.HealthCheck/packages.config b/src/csharp/Grpc.HealthCheck/packages.config
new file mode 100644
index 0000000000..094a30981e
--- /dev/null
+++ b/src/csharp/Grpc.HealthCheck/packages.config
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="Google.ProtocolBuffers" version="2.4.1.555" targetFramework="net45" />
+ <package id="Ix-Async" version="1.2.3" targetFramework="net45" />
+</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.HealthCheck/proto/health.proto b/src/csharp/Grpc.HealthCheck/proto/health.proto
new file mode 100644
index 0000000000..08df7e104e
--- /dev/null
+++ b/src/csharp/Grpc.HealthCheck/proto/health.proto
@@ -0,0 +1,52 @@
+// 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.
+
+// TODO(jtattermusch): switch to proto3 once C# supports that.
+syntax = "proto2";
+
+package grpc.health.v1alpha;
+option csharp_namespace = "Grpc.Health.V1Alpha";
+
+message HealthCheckRequest {
+ optional string host = 1;
+ optional string service = 2;
+}
+
+message HealthCheckResponse {
+ enum ServingStatus {
+ UNKNOWN = 0;
+ SERVING = 1;
+ NOT_SERVING = 2;
+ }
+ optional ServingStatus status = 1;
+}
+
+service Health {
+ rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
+} \ No newline at end of file