UNPKG

@mdf.js/service-registry

Version:

MMS - API - Service Registry

157 lines 6.46 kB
"use strict"; /** * Copyright 2024 Mytra Control S.L. All rights reserved. * * Use of this source code is governed by an MIT-style license that can be found in the LICENSE file * or at https://opensource.org/licenses/MIT. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.HealthFacade = void 0; const tslib_1 = require("tslib"); const logger_1 = require("@mdf.js/logger"); const cluster_1 = tslib_1.__importDefault(require("cluster")); const events_1 = require("events"); const Aggregator_1 = require("./Aggregator"); const Ports_1 = require("./Ports"); const Router_1 = require("./Router"); const types_1 = require("./types"); /** * The HealthFacade class serves as a comprehensive solution for monitoring and exposing the health * of all components within an application. It abstracts the complexity of health information * aggregation and distribution, making it accessible through a REST API and manageable across * different operational contexts (e.g., standalone, clustered master, and worker processes). * * This class leverages: * - Aggregator: To aggregate health checks and status events from components. * - Port: To handle health information requests and responses in a cluster, accommodating both * master and worker roles. * - Router: To expose aggregated health information via a REST API. */ class HealthFacade extends events_1.EventEmitter { /** * Create an instance of health registry * @param options - health registry options */ constructor(options) { super(); this.options = options; /** Event handler for status event */ this.statusEventHandler = () => { if (this.listenerCount('status') > 0) { this.emit('status', this.status); } }; this.logger = (0, logger_1.SetContext)( // Stryker disable next-line all this.options.logger || new logger_1.DebugLogger(`mdf:registry:health:${this.name}`), types_1.HEALTH_SERVICE_NAME, this.options.applicationMetadata.instanceId); this.aggregator = new Aggregator_1.Aggregator(this.options.applicationMetadata, this.logger); this.port = this.getPort(this.options, this.aggregator, this.logger); this._router = new Router_1.Router(this.aggregator); // Stryker disable next-line all this.logger.debug(`New health registry instance created`); } /** * Dynamically selects and initializes the appropriate Port implementation based on the * application's execution context (standalone, clustered master, or worker) to manage * health information exchange. * @param options - health registry options * @param aggregator - health aggregator * @param logger - logger instance * @returns Port to manage the health information */ getPort(options, aggregator, logger) { if (typeof options.isCluster === 'boolean') { return options.isCluster && cluster_1.default.isPrimary ? new Ports_1.MasterPort(aggregator, logger, options.clusterUpdateInterval) : new Ports_1.WorkerPort(aggregator, logger); } return undefined; } /** @returns The application name */ get name() { return this.options.applicationMetadata.name; } /** @returns The application identifier */ get componentId() { return this.options.applicationMetadata.instanceId; } /** @returns An Express router with access to health information */ get router() { return this._router.router; } /** @returns Links offered by this service */ get links() { return { [`${types_1.HEALTH_SERVICE_NAME}`]: `/${types_1.HEALTH_SERVICE_NAME}` }; } /** @returns The health status of the component */ get status() { return this.aggregator.status; } /** @returns Health checks for this service */ get checks() { return this.aggregator.checks; } /** * Adds a timestamped note to the health status. * @param note - Note to be added. */ addNote(note) { this.aggregator.addNote(note); } /** * Register a resource or a list of resources to monitor for errors. * @param component - Resource or list of resources to be registered */ register(component) { this.aggregator.register(component); } /** * Update or add a check measure. * This should be used to inform about the state of resources behind the Component/Microservice, * for example states of connections with field devices. * * The new check will be taking into account in the overall health status. * The new check will be included in the `checks` object with the key "component:measure". * If this key already exists, the `componentId` of the `check` parameter will be checked, if * there is a check with the same `componentId` in the array, the check will be updated, in other * case the new check will be added to the existing array. * * The maximum number external checks is 100 * @param component - component identification * @param measure - measure identification * @param check - check to be updated or included * @returns true, if the check has been updated */ addCheck(component, measure, check) { return this.aggregator.addExternalCheck(component, measure, check); } /** @returns The health of the application */ get health() { return this.aggregator.health; } /** Start health service */ async start() { var _a; // Stryker disable next-line all this.logger.debug('Starting health registry'); (_a = this.port) === null || _a === void 0 ? void 0 : _a.start(); this.aggregator.on('status', this.statusEventHandler); } /** Stop health service */ async stop() { var _a; // Stryker disable next-line all this.logger.debug('Stopping health registry'); (_a = this.port) === null || _a === void 0 ? void 0 : _a.stop(); this.aggregator.off('status', this.statusEventHandler); } /** Close health service */ async close() { // Stryker disable next-line all this.logger.debug('Closing health registry'); await this.stop(); this.aggregator.close(); } } exports.HealthFacade = HealthFacade; //# sourceMappingURL=HealthFacade.js.map