Skip to content

Health list endpoint #2957

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
import type { MethodDefinition } from '@grpc/proto-loader'
import type { HealthCheckRequest as _grpc_health_v1_HealthCheckRequest, HealthCheckRequest__Output as _grpc_health_v1_HealthCheckRequest__Output } from '../../../grpc/health/v1/HealthCheckRequest';
import type { HealthCheckResponse as _grpc_health_v1_HealthCheckResponse, HealthCheckResponse__Output as _grpc_health_v1_HealthCheckResponse__Output } from '../../../grpc/health/v1/HealthCheckResponse';
import type { HealthListRequest as _grpc_health_v1_HealthListRequest, HealthListRequest__Output as _grpc_health_v1_HealthListRequest__Output } from '../../../grpc/health/v1/HealthListRequest';
import type { HealthListResponse as _grpc_health_v1_HealthListResponse, HealthListResponse__Output as _grpc_health_v1_HealthListResponse__Output } from '../../../grpc/health/v1/HealthListResponse';

export interface HealthDefinition {
Check: MethodDefinition<_grpc_health_v1_HealthCheckRequest, _grpc_health_v1_HealthCheckResponse, _grpc_health_v1_HealthCheckRequest__Output, _grpc_health_v1_HealthCheckResponse__Output>
List: MethodDefinition<_grpc_health_v1_HealthListRequest, _grpc_health_v1_HealthListResponse, _grpc_health_v1_HealthListRequest__Output, _grpc_health_v1_HealthListResponse__Output>
Watch: MethodDefinition<_grpc_health_v1_HealthCheckRequest, _grpc_health_v1_HealthCheckResponse, _grpc_health_v1_HealthCheckRequest__Output, _grpc_health_v1_HealthCheckResponse__Output>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Original file: proto/health/v1/health.proto


export interface HealthListRequest {
}

export interface HealthListRequest__Output {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Original file: proto/health/v1/health.proto

import type { HealthCheckResponse as _grpc_health_v1_HealthCheckResponse, HealthCheckResponse__Output as _grpc_health_v1_HealthCheckResponse__Output } from '../../../grpc/health/v1/HealthCheckResponse';

export interface HealthListResponse {
/**
* statuses contains all the services and their respective status.
*/
'statuses'?: ({[key: string]: _grpc_health_v1_HealthCheckResponse});
}

export interface HealthListResponse__Output {
/**
* statuses contains all the services and their respective status.
*/
'statuses': ({[key: string]: _grpc_health_v1_HealthCheckResponse__Output});
}
24 changes: 23 additions & 1 deletion packages/grpc-health-check/src/health.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import { loadSync, ServiceDefinition } from '@grpc/proto-loader';
import { HealthCheckRequest__Output } from './generated/grpc/health/v1/HealthCheckRequest';
import { HealthCheckResponse } from './generated/grpc/health/v1/HealthCheckResponse';
import { sendUnaryData, Server, ServerUnaryCall, ServerWritableStream } from './server-type';
import { HealthListRequest } from './generated/grpc/health/v1/HealthListRequest';
import { HealthListResponse } from './generated/grpc/health/v1/HealthListResponse';

const loadedProto = loadSync('health/v1/health.proto', {
keepCase: true,
Expand All @@ -34,6 +36,8 @@ const loadedProto = loadSync('health/v1/health.proto', {
export const service = loadedProto['grpc.health.v1.Health'] as ServiceDefinition;

const GRPC_STATUS_NOT_FOUND = 5;
const GRPC_STATUS_RESOURCE_EXHAUSTED = 8;
const RESOURCE_EXHAUSTION_LIMIT = 100;

export type ServingStatus = 'UNKNOWN' | 'SERVING' | 'NOT_SERVING';

Expand Down Expand Up @@ -104,7 +108,25 @@ export class HealthImplementation {
} else {
call.write({status: 'SERVICE_UNKNOWN'});
}
}
},
list: (_call: ServerUnaryCall<HealthListRequest, HealthListResponse>, callback: sendUnaryData<HealthListResponse>) => {
const statuses: { [key: string]: HealthCheckResponse } = {};
let serviceCount = 0;

for (const [serviceName, status] of this.statusMap.entries()) {
if (serviceCount >= RESOURCE_EXHAUSTION_LIMIT) {
const error = {
code: GRPC_STATUS_RESOURCE_EXHAUSTED,
details: 'Too many services to list.',
};
callback(error, null);
return;
}
statuses[serviceName] = { status };
serviceCount++;
}
callback(null, { statuses });
},
});
}
}
Expand Down
53 changes: 53 additions & 0 deletions packages/grpc-health-check/test/generated/grpc/health/v1/Health.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import type * as grpc from '@grpc/grpc-js'
import type { MethodDefinition } from '@grpc/proto-loader'
import type { HealthCheckRequest as _grpc_health_v1_HealthCheckRequest, HealthCheckRequest__Output as _grpc_health_v1_HealthCheckRequest__Output } from '../../../grpc/health/v1/HealthCheckRequest';
import type { HealthCheckResponse as _grpc_health_v1_HealthCheckResponse, HealthCheckResponse__Output as _grpc_health_v1_HealthCheckResponse__Output } from '../../../grpc/health/v1/HealthCheckResponse';
import type { HealthListRequest as _grpc_health_v1_HealthListRequest, HealthListRequest__Output as _grpc_health_v1_HealthListRequest__Output } from '../../../grpc/health/v1/HealthListRequest';
import type { HealthListResponse as _grpc_health_v1_HealthListResponse, HealthListResponse__Output as _grpc_health_v1_HealthListResponse__Output } from '../../../grpc/health/v1/HealthListResponse';

/**
* Health is gRPC's mechanism for checking whether a server is able to handle
Expand Down Expand Up @@ -42,6 +44,41 @@ export interface HealthClient extends grpc.Client {
check(argument: _grpc_health_v1_HealthCheckRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_health_v1_HealthCheckResponse__Output>): grpc.ClientUnaryCall;
check(argument: _grpc_health_v1_HealthCheckRequest, callback: grpc.requestCallback<_grpc_health_v1_HealthCheckResponse__Output>): grpc.ClientUnaryCall;

/**
* List provides a non-atomic snapshot of the health of all the available
* services.
*
* The server may respond with a RESOURCE_EXHAUSTED error if too many services
* exist.
*
* Clients should set a deadline when calling List, and can declare the server
* unhealthy if they do not receive a timely response.
*
* Clients should keep in mind that the list of health services exposed by an
* application can change over the lifetime of the process.
*/
List(argument: _grpc_health_v1_HealthListRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_health_v1_HealthListResponse__Output>): grpc.ClientUnaryCall;
List(argument: _grpc_health_v1_HealthListRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_health_v1_HealthListResponse__Output>): grpc.ClientUnaryCall;
List(argument: _grpc_health_v1_HealthListRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_health_v1_HealthListResponse__Output>): grpc.ClientUnaryCall;
List(argument: _grpc_health_v1_HealthListRequest, callback: grpc.requestCallback<_grpc_health_v1_HealthListResponse__Output>): grpc.ClientUnaryCall;
/**
* List provides a non-atomic snapshot of the health of all the available
* services.
*
* The server may respond with a RESOURCE_EXHAUSTED error if too many services
* exist.
*
* Clients should set a deadline when calling List, and can declare the server
* unhealthy if they do not receive a timely response.
*
* Clients should keep in mind that the list of health services exposed by an
* application can change over the lifetime of the process.
*/
list(argument: _grpc_health_v1_HealthListRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_health_v1_HealthListResponse__Output>): grpc.ClientUnaryCall;
list(argument: _grpc_health_v1_HealthListRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_grpc_health_v1_HealthListResponse__Output>): grpc.ClientUnaryCall;
list(argument: _grpc_health_v1_HealthListRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_grpc_health_v1_HealthListResponse__Output>): grpc.ClientUnaryCall;
list(argument: _grpc_health_v1_HealthListRequest, callback: grpc.requestCallback<_grpc_health_v1_HealthListResponse__Output>): grpc.ClientUnaryCall;

/**
* Performs a watch for the serving status of the requested service.
* The server will immediately send back a message indicating the current
Expand Down Expand Up @@ -102,6 +139,21 @@ export interface HealthHandlers extends grpc.UntypedServiceImplementation {
*/
Check: grpc.handleUnaryCall<_grpc_health_v1_HealthCheckRequest__Output, _grpc_health_v1_HealthCheckResponse>;

/**
* List provides a non-atomic snapshot of the health of all the available
* services.
*
* The server may respond with a RESOURCE_EXHAUSTED error if too many services
* exist.
*
* Clients should set a deadline when calling List, and can declare the server
* unhealthy if they do not receive a timely response.
*
* Clients should keep in mind that the list of health services exposed by an
* application can change over the lifetime of the process.
*/
List: grpc.handleUnaryCall<_grpc_health_v1_HealthListRequest__Output, _grpc_health_v1_HealthListResponse>;

/**
* Performs a watch for the serving status of the requested service.
* The server will immediately send back a message indicating the current
Expand All @@ -125,5 +177,6 @@ export interface HealthHandlers extends grpc.UntypedServiceImplementation {

export interface HealthDefinition extends grpc.ServiceDefinition {
Check: MethodDefinition<_grpc_health_v1_HealthCheckRequest, _grpc_health_v1_HealthCheckResponse, _grpc_health_v1_HealthCheckRequest__Output, _grpc_health_v1_HealthCheckResponse__Output>
List: MethodDefinition<_grpc_health_v1_HealthListRequest, _grpc_health_v1_HealthListResponse, _grpc_health_v1_HealthListRequest__Output, _grpc_health_v1_HealthListResponse__Output>
Watch: MethodDefinition<_grpc_health_v1_HealthCheckRequest, _grpc_health_v1_HealthCheckResponse, _grpc_health_v1_HealthCheckRequest__Output, _grpc_health_v1_HealthCheckResponse__Output>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Original file: proto/health/v1/health.proto


export interface HealthListRequest {
}

export interface HealthListRequest__Output {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Original file: proto/health/v1/health.proto

import type { HealthCheckResponse as _grpc_health_v1_HealthCheckResponse, HealthCheckResponse__Output as _grpc_health_v1_HealthCheckResponse__Output } from '../../../grpc/health/v1/HealthCheckResponse';

export interface HealthListResponse {
/**
* statuses contains all the services and their respective status.
*/
'statuses'?: ({[key: string]: _grpc_health_v1_HealthCheckResponse});
}

export interface HealthListResponse__Output {
/**
* statuses contains all the services and their respective status.
*/
'statuses': ({[key: string]: _grpc_health_v1_HealthCheckResponse__Output});
}
2 changes: 2 additions & 0 deletions packages/grpc-health-check/test/generated/health.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export interface ProtoGrpcType {
Health: SubtypeConstructor<typeof grpc.Client, _grpc_health_v1_HealthClient> & { service: _grpc_health_v1_HealthDefinition }
HealthCheckRequest: MessageTypeDefinition
HealthCheckResponse: MessageTypeDefinition
HealthListRequest: MessageTypeDefinition
HealthListResponse: MessageTypeDefinition
}
}
}
Expand Down