Healthcheck Option Checks
Applies to
@connectum/healthcheck1.3.0.
Does this apply to you?
Inputs that used to be accepted and misbehaved later now fail where they are made. You need to act only if one of these is true:
watchIntervalis0, a fraction,NaN, negative,Infinity, above 2147483647, a string ornull.Healthcheck()now throwsRangeError(a number) orTypeError(not a number). Before, the number values made everyHealth.Watchcall poll about once per millisecond, and a string ornullmade everyWatchend with an internal error.Healthcheck()receives a bad option:nullas the options object, amanagerthat is not aHealthcheckManager, or anhttpEnabledthat is not a boolean ("yes"and1used to count as true). It throwsTypeErrornaming the option.- Two
Healthcheck()entries are inprotocols, or the application mounts its owngrpc.health.v1.Healthservice next toHealthcheck().start()(and the first call made throughlocalClient()) now rejects with an error naming the service. Before, the server started and one of the two managers was silently ignored. - A status that is not 0 to 3 is passed to
update(),register()orset()of the manager: a string such as"SERVING",null,undefined, a fraction,99. It throwsTypeErrororRangeErrorand the registry is not changed. Before, the value was stored andHealth.List(for every service) andHealth.Checkof that component failed with an internal error. A component or service name that is not a string throwsTypeError. createHttpHealthHandler(manager, []), or a path list with a bad entry. It throws likehttpPathsdoes inHealthcheck(). Before, it returned a handler that never matched a request.
Valid configurations and valid calls behave as before.
Required changes
Fix the value the error names:
typescript
// watchInterval: pick a whole number of milliseconds, or omit it for 500
Healthcheck({ watchInterval: 250 });
// one registration per server
createServer({ services, protocols: [Healthcheck({ httpEnabled: true })] });
// statuses are the ServingStatus constants
healthcheckManager.set('database', ServingStatus.NOT_SERVING);If an application sets a status from outside input (a config value, a health-source response), map it to a ServingStatus constant first; the manager no longer converts or stores unknown values.
Behavior that changed without an option
Health.Watchdelivers every change. A status that goesNOT_SERVINGand back toSERVINGinside onewatchIntervalused to be invisible to watchers; it is now two messages, and a change no longer waits for the interval. Watchers also see short intermediate states, for exampleUNKNOWNbetween a service being registered and its firstupdate(). A client that counts messages or expects only the states a poll caught sees more of them.watchIntervalremains the period of a re-check.HealthcheckManagergainssubscribe(); a custommanagerpassed toHealthcheck()must have it, which everyHealthcheckManagerdoes.- The
NOT_FOUNDmessage ofHealth.Checkis bounded. It repeats at most the first 128 characters of the requested service name. A client that parses the full name out of the message sees it cut only for names longer than 128 characters. GET /healthz?service=(an empty value) reports"service": "overall"in the body, like a request without the parameter. Before, the field was an empty string.
Verify the upgrade
Start the server. If Healthcheck() or start() throws, the message names the option or the Health service. Then run grpcurl against grpc.health.v1.Health/Watch: while it is open, set a service NOT_SERVING and SERVING back to back; the stream must show both statuses.