Introducing super basic health check for cart service (#44)
* Introducing super basic health check for cart service - Generated C# proto implementation for grpc health check - Moved all C# protos to a dedicated folder - Implemented basic health checking to ping CartStore (which is Redis in default implementation) - Base plumbing for health checks * Introducing super basic health check for cart service - Generated C# proto implementation for grpc health check - Moved all C# protos to a dedicated folder - Implemented basic health checking to ping CartStore (which is Redis in default implementation) - Base plumbing for health checks * Changing Ping health probe to call Redis Cache Ping method
This commit is contained in:
parent
1bab006af1
commit
1f60819dee
9 changed files with 770 additions and 895 deletions
22
src/cartservice/HealthImpl.cs
Normal file
22
src/cartservice/HealthImpl.cs
Normal file
|
@ -0,0 +1,22 @@
|
|||
using System;
|
||||
using cartservice.interfaces;
|
||||
using Grpc.Health.V1;
|
||||
using StackExchange.Redis;
|
||||
using static Grpc.Health.V1.Health;
|
||||
|
||||
namespace cartservice {
|
||||
internal class HealthImpl : HealthBase {
|
||||
private ICartStore dependency { get; }
|
||||
public HealthImpl (ICartStore dependency) {
|
||||
this.dependency = dependency;
|
||||
}
|
||||
|
||||
public HealthCheckResponse Check (HealthCheckRequest request) {
|
||||
Console.WriteLine ("Checking CartService Health");
|
||||
|
||||
return new HealthCheckResponse {
|
||||
Status = dependency.Ping() ? HealthCheckResponse.Types.ServingStatus.Serving : HealthCheckResponse.Types.ServingStatus.NotServing
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -56,7 +56,14 @@ namespace cartservice
|
|||
Console.WriteLine($"Trying to start a grpc server at {host}:{port}");
|
||||
Server server = new Server
|
||||
{
|
||||
Services = { Hipstershop.CartService.BindService(new CartServiceImpl(cartStore)) },
|
||||
Services =
|
||||
{
|
||||
// Cart Service Endpoint
|
||||
Hipstershop.CartService.BindService(new CartServiceImpl(cartStore)),
|
||||
|
||||
// Health Endpoint
|
||||
Grpc.Health.V1.Health.BindService(new HealthImpl(cartStore))
|
||||
},
|
||||
Ports = { new ServerPort(host, port, ServerCredentials.Insecure) }
|
||||
};
|
||||
|
||||
|
|
|
@ -7,9 +7,10 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommandLineParser" Version="2.2.1" />
|
||||
<PackageReference Include="Google.Protobuf" Version="3.5.1" />
|
||||
<PackageReference Include="Google.Protobuf" Version="3.6.1" />
|
||||
<PackageReference Include="Google.Protobuf.Tools" Version="3.5.1" />
|
||||
<PackageReference Include="grpc" Version="1.12.0" />
|
||||
<PackageReference Include="Grpc.HealthCheck" Version="1.15.0" />
|
||||
<PackageReference Include="grpc.tools" Version="1.12.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.1.1" />
|
||||
|
|
|
@ -82,5 +82,10 @@ namespace cartservice.cartstore
|
|||
|
||||
return Task.FromResult(cart);
|
||||
}
|
||||
|
||||
public bool Ping()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -197,5 +197,20 @@ namespace cartservice.cartstore
|
|||
throw new RpcException(new Status(StatusCode.FailedPrecondition, $"Can't access cart storage. {ex}"));
|
||||
}
|
||||
}
|
||||
|
||||
public bool Ping()
|
||||
{
|
||||
try
|
||||
{
|
||||
var redis = ConnectionMultiplexer.Connect(redisConnectionOptions);
|
||||
var cache = redis.GetDatabase();
|
||||
var res = cache.Ping();
|
||||
return res != TimeSpan.Zero;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,6 @@ cd /d %~dp0
|
|||
set NUGET_PATH=%UserProfile%\.nuget\packages
|
||||
set TOOLS_PATH=%NUGET_PATH%\Grpc.Tools\1.12.0\tools\windows_x64
|
||||
|
||||
%TOOLS_PATH%\protoc.exe -I%~dp0/../../pb;%NUGET_PATH%\google.protobuf.tools\3.5.1\tools\ --csharp_out %~dp0 %~dp0\..\..\pb\demo.proto --grpc_out %~dp0 --plugin=protoc-gen-grpc=%TOOLS_PATH%\grpc_csharp_plugin.exe
|
||||
%TOOLS_PATH%\protoc.exe -I%~dp0/../../pb;%NUGET_PATH%\google.protobuf.tools\3.5.1\tools\ --csharp_out %~dp0\grpc_generated %~dp0\..\..\pb\demo.proto --grpc_out %~dp0\grpc_generated --plugin=protoc-gen-grpc=%TOOLS_PATH%\grpc_csharp_plugin.exe
|
||||
|
||||
endlocal
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,17 +1,3 @@
|
|||
// Copyright 2018 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// <auto-generated>
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: demo.proto
|
||||
|
@ -522,8 +508,8 @@ namespace Hipstershop {
|
|||
|
||||
static readonly grpc::Marshaller<global::Hipstershop.Empty> __Marshaller_Empty = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Hipstershop.Empty.Parser.ParseFrom);
|
||||
static readonly grpc::Marshaller<global::Hipstershop.GetSupportedCurrenciesResponse> __Marshaller_GetSupportedCurrenciesResponse = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Hipstershop.GetSupportedCurrenciesResponse.Parser.ParseFrom);
|
||||
static readonly grpc::Marshaller<global::Hipstershop.ConversionRequest> __Marshaller_ConversionRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Hipstershop.ConversionRequest.Parser.ParseFrom);
|
||||
static readonly grpc::Marshaller<global::Hipstershop.ConversionResponse> __Marshaller_ConversionResponse = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Hipstershop.ConversionResponse.Parser.ParseFrom);
|
||||
static readonly grpc::Marshaller<global::Hipstershop.CurrencyConversionRequest> __Marshaller_CurrencyConversionRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Hipstershop.CurrencyConversionRequest.Parser.ParseFrom);
|
||||
static readonly grpc::Marshaller<global::Hipstershop.Money> __Marshaller_Money = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Hipstershop.Money.Parser.ParseFrom);
|
||||
|
||||
static readonly grpc::Method<global::Hipstershop.Empty, global::Hipstershop.GetSupportedCurrenciesResponse> __Method_GetSupportedCurrencies = new grpc::Method<global::Hipstershop.Empty, global::Hipstershop.GetSupportedCurrenciesResponse>(
|
||||
grpc::MethodType.Unary,
|
||||
|
@ -532,12 +518,12 @@ namespace Hipstershop {
|
|||
__Marshaller_Empty,
|
||||
__Marshaller_GetSupportedCurrenciesResponse);
|
||||
|
||||
static readonly grpc::Method<global::Hipstershop.ConversionRequest, global::Hipstershop.ConversionResponse> __Method_Convert = new grpc::Method<global::Hipstershop.ConversionRequest, global::Hipstershop.ConversionResponse>(
|
||||
static readonly grpc::Method<global::Hipstershop.CurrencyConversionRequest, global::Hipstershop.Money> __Method_Convert = new grpc::Method<global::Hipstershop.CurrencyConversionRequest, global::Hipstershop.Money>(
|
||||
grpc::MethodType.Unary,
|
||||
__ServiceName,
|
||||
"Convert",
|
||||
__Marshaller_ConversionRequest,
|
||||
__Marshaller_ConversionResponse);
|
||||
__Marshaller_CurrencyConversionRequest,
|
||||
__Marshaller_Money);
|
||||
|
||||
/// <summary>Service descriptor</summary>
|
||||
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
|
||||
|
@ -553,7 +539,7 @@ namespace Hipstershop {
|
|||
throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
|
||||
}
|
||||
|
||||
public virtual global::System.Threading.Tasks.Task<global::Hipstershop.ConversionResponse> Convert(global::Hipstershop.ConversionRequest request, grpc::ServerCallContext context)
|
||||
public virtual global::System.Threading.Tasks.Task<global::Hipstershop.Money> Convert(global::Hipstershop.CurrencyConversionRequest request, grpc::ServerCallContext context)
|
||||
{
|
||||
throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
|
||||
}
|
||||
|
@ -599,19 +585,19 @@ namespace Hipstershop {
|
|||
{
|
||||
return CallInvoker.AsyncUnaryCall(__Method_GetSupportedCurrencies, null, options, request);
|
||||
}
|
||||
public virtual global::Hipstershop.ConversionResponse Convert(global::Hipstershop.ConversionRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
|
||||
public virtual global::Hipstershop.Money Convert(global::Hipstershop.CurrencyConversionRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
|
||||
{
|
||||
return Convert(request, new grpc::CallOptions(headers, deadline, cancellationToken));
|
||||
}
|
||||
public virtual global::Hipstershop.ConversionResponse Convert(global::Hipstershop.ConversionRequest request, grpc::CallOptions options)
|
||||
public virtual global::Hipstershop.Money Convert(global::Hipstershop.CurrencyConversionRequest request, grpc::CallOptions options)
|
||||
{
|
||||
return CallInvoker.BlockingUnaryCall(__Method_Convert, null, options, request);
|
||||
}
|
||||
public virtual grpc::AsyncUnaryCall<global::Hipstershop.ConversionResponse> ConvertAsync(global::Hipstershop.ConversionRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
|
||||
public virtual grpc::AsyncUnaryCall<global::Hipstershop.Money> ConvertAsync(global::Hipstershop.CurrencyConversionRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
|
||||
{
|
||||
return ConvertAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
|
||||
}
|
||||
public virtual grpc::AsyncUnaryCall<global::Hipstershop.ConversionResponse> ConvertAsync(global::Hipstershop.ConversionRequest request, grpc::CallOptions options)
|
||||
public virtual grpc::AsyncUnaryCall<global::Hipstershop.Money> ConvertAsync(global::Hipstershop.CurrencyConversionRequest request, grpc::CallOptions options)
|
||||
{
|
||||
return CallInvoker.AsyncUnaryCall(__Method_Convert, null, options, request);
|
||||
}
|
||||
|
@ -806,18 +792,9 @@ namespace Hipstershop {
|
|||
{
|
||||
static readonly string __ServiceName = "hipstershop.CheckoutService";
|
||||
|
||||
static readonly grpc::Marshaller<global::Hipstershop.CreateOrderRequest> __Marshaller_CreateOrderRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Hipstershop.CreateOrderRequest.Parser.ParseFrom);
|
||||
static readonly grpc::Marshaller<global::Hipstershop.CreateOrderResponse> __Marshaller_CreateOrderResponse = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Hipstershop.CreateOrderResponse.Parser.ParseFrom);
|
||||
static readonly grpc::Marshaller<global::Hipstershop.PlaceOrderRequest> __Marshaller_PlaceOrderRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Hipstershop.PlaceOrderRequest.Parser.ParseFrom);
|
||||
static readonly grpc::Marshaller<global::Hipstershop.PlaceOrderResponse> __Marshaller_PlaceOrderResponse = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Hipstershop.PlaceOrderResponse.Parser.ParseFrom);
|
||||
|
||||
static readonly grpc::Method<global::Hipstershop.CreateOrderRequest, global::Hipstershop.CreateOrderResponse> __Method_CreateOrder = new grpc::Method<global::Hipstershop.CreateOrderRequest, global::Hipstershop.CreateOrderResponse>(
|
||||
grpc::MethodType.Unary,
|
||||
__ServiceName,
|
||||
"CreateOrder",
|
||||
__Marshaller_CreateOrderRequest,
|
||||
__Marshaller_CreateOrderResponse);
|
||||
|
||||
static readonly grpc::Method<global::Hipstershop.PlaceOrderRequest, global::Hipstershop.PlaceOrderResponse> __Method_PlaceOrder = new grpc::Method<global::Hipstershop.PlaceOrderRequest, global::Hipstershop.PlaceOrderResponse>(
|
||||
grpc::MethodType.Unary,
|
||||
__ServiceName,
|
||||
|
@ -834,11 +811,6 @@ namespace Hipstershop {
|
|||
/// <summary>Base class for server-side implementations of CheckoutService</summary>
|
||||
public abstract partial class CheckoutServiceBase
|
||||
{
|
||||
public virtual global::System.Threading.Tasks.Task<global::Hipstershop.CreateOrderResponse> CreateOrder(global::Hipstershop.CreateOrderRequest request, grpc::ServerCallContext context)
|
||||
{
|
||||
throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
|
||||
}
|
||||
|
||||
public virtual global::System.Threading.Tasks.Task<global::Hipstershop.PlaceOrderResponse> PlaceOrder(global::Hipstershop.PlaceOrderRequest request, grpc::ServerCallContext context)
|
||||
{
|
||||
throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
|
||||
|
@ -869,22 +841,6 @@ namespace Hipstershop {
|
|||
{
|
||||
}
|
||||
|
||||
public virtual global::Hipstershop.CreateOrderResponse CreateOrder(global::Hipstershop.CreateOrderRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
|
||||
{
|
||||
return CreateOrder(request, new grpc::CallOptions(headers, deadline, cancellationToken));
|
||||
}
|
||||
public virtual global::Hipstershop.CreateOrderResponse CreateOrder(global::Hipstershop.CreateOrderRequest request, grpc::CallOptions options)
|
||||
{
|
||||
return CallInvoker.BlockingUnaryCall(__Method_CreateOrder, null, options, request);
|
||||
}
|
||||
public virtual grpc::AsyncUnaryCall<global::Hipstershop.CreateOrderResponse> CreateOrderAsync(global::Hipstershop.CreateOrderRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
|
||||
{
|
||||
return CreateOrderAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
|
||||
}
|
||||
public virtual grpc::AsyncUnaryCall<global::Hipstershop.CreateOrderResponse> CreateOrderAsync(global::Hipstershop.CreateOrderRequest request, grpc::CallOptions options)
|
||||
{
|
||||
return CallInvoker.AsyncUnaryCall(__Method_CreateOrder, null, options, request);
|
||||
}
|
||||
public virtual global::Hipstershop.PlaceOrderResponse PlaceOrder(global::Hipstershop.PlaceOrderRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
|
||||
{
|
||||
return PlaceOrder(request, new grpc::CallOptions(headers, deadline, cancellationToken));
|
||||
|
@ -913,10 +869,94 @@ namespace Hipstershop {
|
|||
public static grpc::ServerServiceDefinition BindService(CheckoutServiceBase serviceImpl)
|
||||
{
|
||||
return grpc::ServerServiceDefinition.CreateBuilder()
|
||||
.AddMethod(__Method_CreateOrder, serviceImpl.CreateOrder)
|
||||
.AddMethod(__Method_PlaceOrder, serviceImpl.PlaceOrder).Build();
|
||||
}
|
||||
|
||||
}
|
||||
public static partial class AdService
|
||||
{
|
||||
static readonly string __ServiceName = "hipstershop.AdService";
|
||||
|
||||
static readonly grpc::Marshaller<global::Hipstershop.AdRequest> __Marshaller_AdRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Hipstershop.AdRequest.Parser.ParseFrom);
|
||||
static readonly grpc::Marshaller<global::Hipstershop.AdResponse> __Marshaller_AdResponse = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Hipstershop.AdResponse.Parser.ParseFrom);
|
||||
|
||||
static readonly grpc::Method<global::Hipstershop.AdRequest, global::Hipstershop.AdResponse> __Method_GetAds = new grpc::Method<global::Hipstershop.AdRequest, global::Hipstershop.AdResponse>(
|
||||
grpc::MethodType.Unary,
|
||||
__ServiceName,
|
||||
"GetAds",
|
||||
__Marshaller_AdRequest,
|
||||
__Marshaller_AdResponse);
|
||||
|
||||
/// <summary>Service descriptor</summary>
|
||||
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
|
||||
{
|
||||
get { return global::Hipstershop.DemoReflection.Descriptor.Services[8]; }
|
||||
}
|
||||
|
||||
/// <summary>Base class for server-side implementations of AdService</summary>
|
||||
public abstract partial class AdServiceBase
|
||||
{
|
||||
public virtual global::System.Threading.Tasks.Task<global::Hipstershop.AdResponse> GetAds(global::Hipstershop.AdRequest request, grpc::ServerCallContext context)
|
||||
{
|
||||
throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>Client for AdService</summary>
|
||||
public partial class AdServiceClient : grpc::ClientBase<AdServiceClient>
|
||||
{
|
||||
/// <summary>Creates a new client for AdService</summary>
|
||||
/// <param name="channel">The channel to use to make remote calls.</param>
|
||||
public AdServiceClient(grpc::Channel channel) : base(channel)
|
||||
{
|
||||
}
|
||||
/// <summary>Creates a new client for AdService that uses a custom <c>CallInvoker</c>.</summary>
|
||||
/// <param name="callInvoker">The callInvoker to use to make remote calls.</param>
|
||||
public AdServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker)
|
||||
{
|
||||
}
|
||||
/// <summary>Protected parameterless constructor to allow creation of test doubles.</summary>
|
||||
protected AdServiceClient() : base()
|
||||
{
|
||||
}
|
||||
/// <summary>Protected constructor to allow creation of configured clients.</summary>
|
||||
/// <param name="configuration">The client configuration.</param>
|
||||
protected AdServiceClient(ClientBaseConfiguration configuration) : base(configuration)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual global::Hipstershop.AdResponse GetAds(global::Hipstershop.AdRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
|
||||
{
|
||||
return GetAds(request, new grpc::CallOptions(headers, deadline, cancellationToken));
|
||||
}
|
||||
public virtual global::Hipstershop.AdResponse GetAds(global::Hipstershop.AdRequest request, grpc::CallOptions options)
|
||||
{
|
||||
return CallInvoker.BlockingUnaryCall(__Method_GetAds, null, options, request);
|
||||
}
|
||||
public virtual grpc::AsyncUnaryCall<global::Hipstershop.AdResponse> GetAdsAsync(global::Hipstershop.AdRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
|
||||
{
|
||||
return GetAdsAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
|
||||
}
|
||||
public virtual grpc::AsyncUnaryCall<global::Hipstershop.AdResponse> GetAdsAsync(global::Hipstershop.AdRequest request, grpc::CallOptions options)
|
||||
{
|
||||
return CallInvoker.AsyncUnaryCall(__Method_GetAds, null, options, request);
|
||||
}
|
||||
/// <summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary>
|
||||
protected override AdServiceClient NewInstance(ClientBaseConfiguration configuration)
|
||||
{
|
||||
return new AdServiceClient(configuration);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Creates service definition that can be registered with a server</summary>
|
||||
/// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
|
||||
public static grpc::ServerServiceDefinition BindService(AdServiceBase serviceImpl)
|
||||
{
|
||||
return grpc::ServerServiceDefinition.CreateBuilder()
|
||||
.AddMethod(__Method_GetAds, serviceImpl.GetAds).Build();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endregion
|
|
@ -24,5 +24,7 @@ namespace cartservice.interfaces
|
|||
Task EmptyCartAsync(string userId);
|
||||
|
||||
Task<Hipstershop.Cart> GetCartAsync(string userId);
|
||||
|
||||
bool Ping();
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue