diff --git a/packages/grpc-health-check/src/generated/grpc/health/v1/Health.ts b/packages/grpc-health-check/src/generated/grpc/health/v1/Health.ts index a308498f4..bd95d638b 100644 --- a/packages/grpc-health-check/src/generated/grpc/health/v1/Health.ts +++ b/packages/grpc-health-check/src/generated/grpc/health/v1/Health.ts @@ -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> } diff --git a/packages/grpc-health-check/src/generated/grpc/health/v1/HealthListRequest.ts b/packages/grpc-health-check/src/generated/grpc/health/v1/HealthListRequest.ts new file mode 100644 index 000000000..fdbf540ca --- /dev/null +++ b/packages/grpc-health-check/src/generated/grpc/health/v1/HealthListRequest.ts @@ -0,0 +1,8 @@ +// Original file: proto/health/v1/health.proto + + +export interface HealthListRequest { +} + +export interface HealthListRequest__Output { +} diff --git a/packages/grpc-health-check/src/generated/grpc/health/v1/HealthListResponse.ts b/packages/grpc-health-check/src/generated/grpc/health/v1/HealthListResponse.ts new file mode 100644 index 000000000..9e5373ca6 --- /dev/null +++ b/packages/grpc-health-check/src/generated/grpc/health/v1/HealthListResponse.ts @@ -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}); +} diff --git a/packages/grpc-health-check/src/health.ts b/packages/grpc-health-check/src/health.ts index 86ca1af0d..b0a8769e7 100644 --- a/packages/grpc-health-check/src/health.ts +++ b/packages/grpc-health-check/src/health.ts @@ -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, @@ -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'; @@ -104,7 +108,25 @@ export class HealthImplementation { } else { call.write({status: 'SERVICE_UNKNOWN'}); } - } + }, + list: (_call: ServerUnaryCall, callback: sendUnaryData) => { + 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 }); + }, }); } } diff --git a/packages/grpc-health-check/test/generated/grpc/health/v1/Health.ts b/packages/grpc-health-check/test/generated/grpc/health/v1/Health.ts index 320958e3c..8888eb43b 100644 --- a/packages/grpc-health-check/test/generated/grpc/health/v1/Health.ts +++ b/packages/grpc-health-check/test/generated/grpc/health/v1/Health.ts @@ -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 @@ -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 @@ -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 @@ -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> } diff --git a/packages/grpc-health-check/test/generated/grpc/health/v1/HealthListRequest.ts b/packages/grpc-health-check/test/generated/grpc/health/v1/HealthListRequest.ts new file mode 100644 index 000000000..fdbf540ca --- /dev/null +++ b/packages/grpc-health-check/test/generated/grpc/health/v1/HealthListRequest.ts @@ -0,0 +1,8 @@ +// Original file: proto/health/v1/health.proto + + +export interface HealthListRequest { +} + +export interface HealthListRequest__Output { +} diff --git a/packages/grpc-health-check/test/generated/grpc/health/v1/HealthListResponse.ts b/packages/grpc-health-check/test/generated/grpc/health/v1/HealthListResponse.ts new file mode 100644 index 000000000..9e5373ca6 --- /dev/null +++ b/packages/grpc-health-check/test/generated/grpc/health/v1/HealthListResponse.ts @@ -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}); +} diff --git a/packages/grpc-health-check/test/generated/health.ts b/packages/grpc-health-check/test/generated/health.ts index afb2ced5f..d5947cdff 100644 --- a/packages/grpc-health-check/test/generated/health.ts +++ b/packages/grpc-health-check/test/generated/health.ts @@ -19,6 +19,8 @@ export interface ProtoGrpcType { Health: SubtypeConstructor & { service: _grpc_health_v1_HealthDefinition } HealthCheckRequest: MessageTypeDefinition HealthCheckResponse: MessageTypeDefinition + HealthListRequest: MessageTypeDefinition + HealthListResponse: MessageTypeDefinition } } }