1 #region Copyright notice and license 2 // Copyright 2015 gRPC authors. 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 #endregion 16 17 using System; 18 using System.Collections.Generic; 19 using System.Linq; 20 using System.Text; 21 using System.Threading.Tasks; 22 23 using Grpc.Core; 24 using Grpc.Core.Utils; 25 using Grpc.Health.V1; 26 27 namespace Grpc.HealthCheck 28 { 29 /// <summary> 30 /// Implementation of a simple Health service. Useful for health checking. 31 /// 32 /// Registering service with a server: 33 /// <code> 34 /// var serviceImpl = new HealthServiceImpl(); 35 /// server = new Server(); 36 /// server.AddServiceDefinition(Grpc.Health.V1.Health.BindService(serviceImpl)); 37 /// </code> 38 /// </summary> 39 public class HealthServiceImpl : Grpc.Health.V1.Health.HealthBase 40 { 41 private readonly object myLock = new object(); 42 private readonly Dictionary<string, HealthCheckResponse.Types.ServingStatus> statusMap = 43 new Dictionary<string, HealthCheckResponse.Types.ServingStatus>(); 44 45 /// <summary> 46 /// Sets the health status for given service. 47 /// </summary> 48 /// <param name="service">The service. Cannot be null.</param> 49 /// <param name="status">the health status</param> SetStatus(string service, HealthCheckResponse.Types.ServingStatus status)50 public void SetStatus(string service, HealthCheckResponse.Types.ServingStatus status) 51 { 52 lock (myLock) 53 { 54 statusMap[service] = status; 55 } 56 } 57 58 /// <summary> 59 /// Clears health status for given service. 60 /// </summary> 61 /// <param name="service">The service. Cannot be null.</param> ClearStatus(string service)62 public void ClearStatus(string service) 63 { 64 lock (myLock) 65 { 66 statusMap.Remove(service); 67 } 68 } 69 70 /// <summary> 71 /// Clears statuses for all services. 72 /// </summary> ClearAll()73 public void ClearAll() 74 { 75 lock (myLock) 76 { 77 statusMap.Clear(); 78 } 79 } 80 81 /// <summary> 82 /// Performs a health status check. 83 /// </summary> 84 /// <param name="request">The check request.</param> 85 /// <param name="context">The call context.</param> 86 /// <returns>The asynchronous response.</returns> Check(HealthCheckRequest request, ServerCallContext context)87 public override Task<HealthCheckResponse> Check(HealthCheckRequest request, ServerCallContext context) 88 { 89 lock (myLock) 90 { 91 var service = request.Service; 92 93 HealthCheckResponse.Types.ServingStatus status; 94 if (!statusMap.TryGetValue(service, out status)) 95 { 96 // TODO(jtattermusch): returning specific status from server handler is not supported yet. 97 throw new RpcException(new Status(StatusCode.NotFound, "")); 98 } 99 return Task.FromResult(new HealthCheckResponse { Status = status }); 100 } 101 } 102 } 103 } 104