/** * @author Martin Karkowski * @email m.karkowski@zema.de * @create date 2021-02-09 11:26:58 * @modify date 2021-08-11 10:34:04 * @desc [description] */ import { ENopeDispatcherStatus, IDispatcherInfo, INopeDispatcherOptions } from "../types/nope/nopeDispatcher.interface"; import { INopeModule, INopeModuleDescription } from "../types/nope/nopeModule.interface"; import { INopeObservable } from "../types/nope/nopeObservable.interface"; import { nopeDispatcher } from "./nopeDispatcher"; export type HostInfo = { cpu: string; cores: number; os: string; ram: number; name: string; disptachers: { pid: number; id: string; status: ENopeDispatcherStatus; timestamp: number; }[]; status: ENopeDispatcherStatus; instances: { identifier: string, status: ENopeDispatcherStatus, dispatcher: string }[]; timestamp: number; }; /** * Create an Enhanced Class, using the * * @export * @class nopeDispatcherManager * @extends {nopeDispatcher} */ export class nopeDispatcherManager extends nopeDispatcher { public readonly onDispatcherWentOffline: INopeObservable public readonly onDispatcherWentOnline: INopeObservable private __knownDispatchers: Array; constructor(options: INopeDispatcherOptions, _generateObservable: () => INopeObservable) { super(options, _generateObservable); this.onDispatcherWentOffline = _generateObservable(); this.onDispatcherWentOnline = _generateObservable(); this.__knownDispatchers = []; } public async _init() { await super._init(); const _this = this; // Initally store the known Dispatchers. this.__knownDispatchers = this.externalDispatchers.getContent(); // Subscribe to Changes. this.externalDispatchers.subscribe(dispatchers => { const _newDispatchers = dispatchers.map(item => item.id); const _oldDispatchers = _this.__knownDispatchers.map(item => item.id); // Determine the newly Addded Dispatchers: const _added = dispatchers.filter(dispatcher => !_oldDispatchers.includes(dispatcher.id)); // Determine the removed Dispatchers: const _removed = _this.__knownDispatchers.filter(dispatcher => !_newDispatchers.includes(dispatcher.id)); _this.onDispatcherWentOnline.setContent(_added); _this.onDispatcherWentOffline.setContent(_removed); // Store the Updated Disaptchers. _this.__knownDispatchers = dispatchers; }); } /** * Function to get all hosts. * * @return {*} {string[]} * @memberof nopeDispatcherManager */ public getAllHosts(): string[] { const hosts = new Set(); for (const info of this._externalDispatchers.values()) { hosts.add(info.host.name); } return Array.from(hosts); } /** * Return the instances of the given Type. * * @param {string} type * @return {*} {INopeModuleDescription[]} * @memberof nopeDispatcherManager */ public async getInstancesOfType(type: string) { const indentifier = this.availableInstances.getContent() .filter(item => item.type == type) .map(item => item.identifier); const promises: Promise[] = []; for (const identifier of indentifier) { promises.push(this.generateInstance({ identifier, type, params: [] })); } // Wait to generate all Instances. const result = await Promise.all(promises); return result; } public getInstanceDescription(identifier: string): INopeModuleDescription | null { if (this._externalInstances.has(identifier)) { return this._externalInstances.get(identifier); } return null; } public getInstanceDescriptionForType(identifier: string): INopeModuleDescription | null { for (const description of this._externalInstances.values()) { if (description.type === identifier) { return description; } } return null; } public getHostInfos(): { [index: string]: HostInfo } { // Define a dataset, which contains the // hosts. const sorted: { [index: string]: HostInfo } = {}; for (const dispatcher of this._externalDispatchers.values()) { // If required, define the Base Element. if (sorted[dispatcher.host.name] === undefined) { sorted[dispatcher.host.name] = { cores: dispatcher.host.cores, cpu: dispatcher.host.cpu, name: dispatcher.host.name, os: dispatcher.host.os, disptachers: [], instances: [], ram: dispatcher.host.ram, status: ENopeDispatcherStatus.HEALTHY, timestamp: dispatcher.timestamp }; } if (this._mappingOfRemoteDispatchersAndInstances.has(dispatcher.id)) { // Add the Instances: for (const instance of this._mappingOfRemoteDispatchersAndInstances.get(dispatcher.id)) { sorted[dispatcher.host.name].instances.push({ identifier: instance.identifier, status: dispatcher.status, dispatcher: dispatcher.id }); } } // Define the state of overall state of this node. sorted[dispatcher.host.name].status = Math.max( sorted[dispatcher.host.name].status, dispatcher.status ); // Define the timestamp of the overall node. sorted[dispatcher.host.name].timestamp = Math.min( sorted[dispatcher.host.name].timestamp, dispatcher.timestamp ); // Store the Dispatcher Status sorted[dispatcher.host.name].disptachers.push({ id: dispatcher.id, status: dispatcher.status, timestamp: dispatcher.timestamp, pid: dispatcher.pid as number }); } return sorted; } }