Skip to content

Commit 71936fa

Browse files
authored
Merge pull request #2575 from murgatroid99/health-check_2.0
grpc-health-check: Version 2.0
2 parents 32c816c + 524bb7d commit 71936fa

File tree

18 files changed

+858
-192
lines changed

18 files changed

+858
-192
lines changed

packages/grpc-health-check/README.md

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,7 @@ Health check client and service for use with gRPC-node.
44

55
## Background
66

7-
This package exports both a client and server that adhere to the [gRPC Health Checking Protocol](https://github.com/grpc/grpc/blob/master/doc/health-checking.md).
8-
9-
By using this package, clients and servers can rely on common proto and service definitions. This means:
10-
- Clients can use the generated stubs to health check _any_ server that adheres to the protocol.
11-
- Servers do not reimplement common logic for publishing health statuses.
7+
This package provides an implementation of the [gRPC Health Checking Protocol](https://github.com/grpc/grpc/blob/master/doc/health-checking.md) service, as described in [gRFC L106](https://github.com/grpc/proposal/blob/master/L106-node-heath-check-library.md).
128

139
## Installation
1410

@@ -22,33 +18,39 @@ npm install grpc-health-check
2218

2319
### Server
2420

25-
Any gRPC-node server can use `grpc-health-check` to adhere to the gRPC Health Checking Protocol.
21+
Any gRPC-node server can use `grpc-health-check` to adhere to the gRPC Health Checking Protocol.
2622
The following shows how this package can be added to a pre-existing gRPC server.
2723

28-
```javascript 1.8
24+
```typescript
2925
// Import package
30-
let health = require('grpc-health-check');
26+
import { HealthImplementation, ServingStatusMap } from 'grpc-health-check';
3127

3228
// Define service status map. Key is the service name, value is the corresponding status.
33-
// By convention, the empty string "" key represents that status of the entire server.
29+
// By convention, the empty string '' key represents that status of the entire server.
3430
const statusMap = {
35-
"ServiceFoo": proto.grpc.health.v1.HealthCheckResponse.ServingStatus.SERVING,
36-
"ServiceBar": proto.grpc.health.v1.HealthCheckResponse.ServingStatus.NOT_SERVING,
37-
"": proto.grpc.health.v1.HealthCheckResponse.ServingStatus.NOT_SERVING,
31+
'ServiceFoo': 'SERVING',
32+
'ServiceBar': 'NOT_SERVING',
33+
'': 'NOT_SERVING',
3834
};
3935

4036
// Construct the service implementation
41-
let healthImpl = new health.Implementation(statusMap);
37+
const healthImpl = new HealthImplementation(statusMap);
38+
39+
healthImpl.addToServer(server);
4240

43-
// Add the service and implementation to your pre-existing gRPC-node server
44-
server.addService(health.service, healthImpl);
41+
// When ServiceBar comes up
42+
healthImpl.setStatus('serviceBar', 'SERVING');
4543
```
4644

4745
Congrats! Your server now allows any client to run a health check against it.
4846

4947
### Client
5048

51-
Any gRPC-node client can use `grpc-health-check` to run health checks against other servers that follow the protocol.
49+
Any gRPC-node client can use the `service` object exported by `grpc-health-check` to generate clients that can make health check requests.
50+
51+
### Command Line Usage
52+
53+
The absolute path to `health.proto` can be obtained on the command line with `node -p 'require("grpc-health-check").protoPath'`.
5254

5355
## Contributing
5456

packages/grpc-health-check/gulpfile.ts

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,32 @@ import * as gulp from 'gulp';
1919
import * as mocha from 'gulp-mocha';
2020
import * as execa from 'execa';
2121
import * as path from 'path';
22-
import * as del from 'del';
23-
import {linkSync} from '../../util';
2422

2523
const healthCheckDir = __dirname;
26-
const baseDir = path.resolve(healthCheckDir, '..', '..');
27-
const testDir = path.resolve(healthCheckDir, 'test');
24+
const outDir = path.resolve(healthCheckDir, 'build');
2825

29-
const runInstall = () => execa('npm', ['install', '--unsafe-perm'], {cwd: healthCheckDir, stdio: 'inherit'});
26+
const execNpmVerb = (verb: string, ...args: string[]) =>
27+
execa('npm', [verb, ...args], {cwd: healthCheckDir, stdio: 'inherit'});
28+
const execNpmCommand = execNpmVerb.bind(null, 'run');
3029

31-
const runRebuild = () => execa('npm', ['rebuild', '--unsafe-perm'], {cwd: healthCheckDir, stdio: 'inherit'});
30+
const install = () => execNpmVerb('install', '--unsafe-perm');
3231

33-
const install = gulp.series(runInstall, runRebuild);
32+
/**
33+
* Transpiles TypeScript files in src/ to JavaScript according to the settings
34+
* found in tsconfig.json.
35+
*/
36+
const compile = () => execNpmCommand('compile');
37+
38+
const runTests = () => {
39+
return gulp.src(`${outDir}/test/**/*.js`)
40+
.pipe(mocha({reporter: 'mocha-jenkins-reporter',
41+
require: ['ts-node/register']}));
42+
};
3443

35-
const test = () => gulp.src(`${testDir}/*.js`).pipe(mocha({reporter: 'mocha-jenkins-reporter'}));
44+
const test = gulp.series(install, runTests);
3645

3746
export {
3847
install,
48+
compile,
3949
test
40-
}
50+
}

packages/grpc-health-check/health.js

Lines changed: 0 additions & 55 deletions
This file was deleted.
Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "grpc-health-check",
3-
"version": "1.8.0",
3+
"version": "2.0.0",
44
"author": "Google Inc.",
55
"description": "Health check client and service for use with gRPC-node",
66
"repository": {
@@ -14,18 +14,27 @@
1414
"email": "[email protected]"
1515
}
1616
],
17+
"scripts": {
18+
"compile": "tsc -p .",
19+
"prepare": "npm run generate-types && npm run compile",
20+
"generate-types": "proto-loader-gen-types --keepCase --longs String --enums String --defaults --oneofs --includeComments --includeDirs proto/ -O src/generated health/v1/health.proto",
21+
"generate-test-types": "proto-loader-gen-types --keepCase --longs String --enums String --defaults --oneofs --includeComments --includeDirs proto/ -O test/generated --grpcLib=@grpc/grpc-js health/v1/health.proto"
22+
},
1723
"dependencies": {
18-
"google-protobuf": "^3.4.0",
19-
"grpc": "^1.6.0",
20-
"lodash.clone": "^4.5.0",
21-
"lodash.get": "^4.4.2"
24+
"@grpc/proto-loader": "^0.7.10",
25+
"typescript": "^5.2.2"
2226
},
2327
"files": [
2428
"LICENSE",
2529
"README.md",
26-
"health.js",
27-
"v1"
30+
"src",
31+
"build",
32+
"proto"
2833
],
29-
"main": "health.js",
30-
"license": "Apache-2.0"
34+
"main": "build/src/health.js",
35+
"types": "build/src/health.d.ts",
36+
"license": "Apache-2.0",
37+
"devDependencies": {
38+
"@grpc/grpc-js": "file:../grpc-js"
39+
}
3140
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Copyright 2015 The gRPC Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// The canonical version of this proto can be found at
16+
// https://github.com/grpc/grpc-proto/blob/master/grpc/health/v1/health.proto
17+
18+
syntax = "proto3";
19+
20+
package grpc.health.v1;
21+
22+
option csharp_namespace = "Grpc.Health.V1";
23+
option go_package = "google.golang.org/grpc/health/grpc_health_v1";
24+
option java_multiple_files = true;
25+
option java_outer_classname = "HealthProto";
26+
option java_package = "io.grpc.health.v1";
27+
28+
message HealthCheckRequest {
29+
string service = 1;
30+
}
31+
32+
message HealthCheckResponse {
33+
enum ServingStatus {
34+
UNKNOWN = 0;
35+
SERVING = 1;
36+
NOT_SERVING = 2;
37+
SERVICE_UNKNOWN = 3; // Used only by the Watch method.
38+
}
39+
ServingStatus status = 1;
40+
}
41+
42+
// Health is gRPC's mechanism for checking whether a server is able to handle
43+
// RPCs. Its semantics are documented in
44+
// https://github.com/grpc/grpc/blob/master/doc/health-checking.md.
45+
service Health {
46+
// Check gets the health of the specified service. If the requested service
47+
// is unknown, the call will fail with status NOT_FOUND. If the caller does
48+
// not specify a service name, the server should respond with its overall
49+
// health status.
50+
//
51+
// Clients should set a deadline when calling Check, and can declare the
52+
// server unhealthy if they do not receive a timely response.
53+
//
54+
// Check implementations should be idempotent and side effect free.
55+
rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
56+
57+
// Performs a watch for the serving status of the requested service.
58+
// The server will immediately send back a message indicating the current
59+
// serving status. It will then subsequently send a new message whenever
60+
// the service's serving status changes.
61+
//
62+
// If the requested service is unknown when the call is received, the
63+
// server will send a message setting the serving status to
64+
// SERVICE_UNKNOWN but will *not* terminate the call. If at some
65+
// future point, the serving status of the service becomes known, the
66+
// server will send a new message with the service's serving status.
67+
//
68+
// If the call terminates with status UNIMPLEMENTED, then clients
69+
// should assume this method is not supported and should not retry the
70+
// call. If the call terminates with any other status (including OK),
71+
// clients should retry the call with appropriate exponential backoff.
72+
rpc Watch(HealthCheckRequest) returns (stream HealthCheckResponse);
73+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Original file: proto/health/v1/health.proto
2+
3+
import type { MethodDefinition } from '@grpc/proto-loader'
4+
import type { HealthCheckRequest as _grpc_health_v1_HealthCheckRequest, HealthCheckRequest__Output as _grpc_health_v1_HealthCheckRequest__Output } from '../../../grpc/health/v1/HealthCheckRequest';
5+
import type { HealthCheckResponse as _grpc_health_v1_HealthCheckResponse, HealthCheckResponse__Output as _grpc_health_v1_HealthCheckResponse__Output } from '../../../grpc/health/v1/HealthCheckResponse';
6+
7+
export interface HealthDefinition {
8+
Check: MethodDefinition<_grpc_health_v1_HealthCheckRequest, _grpc_health_v1_HealthCheckResponse, _grpc_health_v1_HealthCheckRequest__Output, _grpc_health_v1_HealthCheckResponse__Output>
9+
Watch: MethodDefinition<_grpc_health_v1_HealthCheckRequest, _grpc_health_v1_HealthCheckResponse, _grpc_health_v1_HealthCheckRequest__Output, _grpc_health_v1_HealthCheckResponse__Output>
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Original file: proto/health/v1/health.proto
2+
3+
4+
export interface HealthCheckRequest {
5+
'service'?: (string);
6+
}
7+
8+
export interface HealthCheckRequest__Output {
9+
'service': (string);
10+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Original file: proto/health/v1/health.proto
2+
3+
4+
// Original file: proto/health/v1/health.proto
5+
6+
export const _grpc_health_v1_HealthCheckResponse_ServingStatus = {
7+
UNKNOWN: 'UNKNOWN',
8+
SERVING: 'SERVING',
9+
NOT_SERVING: 'NOT_SERVING',
10+
/**
11+
* Used only by the Watch method.
12+
*/
13+
SERVICE_UNKNOWN: 'SERVICE_UNKNOWN',
14+
} as const;
15+
16+
export type _grpc_health_v1_HealthCheckResponse_ServingStatus =
17+
| 'UNKNOWN'
18+
| 0
19+
| 'SERVING'
20+
| 1
21+
| 'NOT_SERVING'
22+
| 2
23+
/**
24+
* Used only by the Watch method.
25+
*/
26+
| 'SERVICE_UNKNOWN'
27+
| 3
28+
29+
export type _grpc_health_v1_HealthCheckResponse_ServingStatus__Output = typeof _grpc_health_v1_HealthCheckResponse_ServingStatus[keyof typeof _grpc_health_v1_HealthCheckResponse_ServingStatus]
30+
31+
export interface HealthCheckResponse {
32+
'status'?: (_grpc_health_v1_HealthCheckResponse_ServingStatus);
33+
}
34+
35+
export interface HealthCheckResponse__Output {
36+
'status': (_grpc_health_v1_HealthCheckResponse_ServingStatus__Output);
37+
}

0 commit comments

Comments
 (0)