nope-js-node
Version:
NoPE Runtime for Nodejs. For Browser-Support please use nope-browser
844 lines (843 loc) • 35.5 kB
JavaScript
"use strict";
/**
* @author Martin Karkowski
* @email m.karkowski@zema.de
* @create date 2020-01-03 11:52:00
* @modify date 2022-01-05 17:51:09
* @desc [description]
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.NopeRpcManager = void 0;
const index_1 = require("../../eventEmitter/index");
const async_1 = require("../../helpers/async");
const idMethods_1 = require("../../helpers/idMethods");
const mergedData_1 = require("../../helpers/mergedData");
const objectMethods_1 = require("../../helpers/objectMethods");
const path_1 = require("../../helpers/path");
const gc_1 = require("../../helpers/gc");
const getLogger_1 = require("../../logger/getLogger");
const index_browser_1 = require("../../logger/index.browser");
const nopePromise_1 = require("../../promise/nopePromise");
const index_2 = require("../ConnectivityManager/index");
/**
* A Dispatcher to perform a function on a Remote
* Dispatcher. Therefore a Task is created and forwarded
* to the remote.
*
* For a detailled description please checkout {@link INopeRpcManager}
*
* @export
* @class nopeDispatcher
*/
class NopeRpcManager {
/**
* Creates an instance of NopeRpcManager.
* @param {INopeDispatcherOptions} options The Options, used by the rpc-manager.
* @param {<T>() => INopeObservable<T>} _generateObservable helper to generate an nope observable. might be used to replace the default observable.
* @param {ValidSelectorFunction} _defaultSelector Default selector see {@link INopeRpcManager.performCall}
* @param {string} [_id=null] A Provided a for the rpc-manager
* @param {INopeConnectivityManager} [_connectivityManager=null] A {@link INopeConnectivityManager} used to listen for new and dead dispatchers
*/
constructor(options, _generateObservable, _defaultSelector, _id = null, _connectivityManager = null) {
this.options = options;
this._generateObservable = _generateObservable;
this._defaultSelector = _defaultSelector;
this._id = _id;
this._connectivityManager = _connectivityManager;
this._communicator = options.communicator;
if (_id == null) {
this._id = (0, idMethods_1.generateId)();
}
if (_connectivityManager == null) {
// Creating a new Status-Manager.
this._connectivityManager = new index_2.NopeConnectivityManager(options, _generateObservable, this._id);
}
this._logger = (0, getLogger_1.defineNopeLogger)(options.logger, `core.rpc-manager`);
// Flag to show if the system is ready or not.
this.ready = this._generateObservable();
this.ready.setContent(false);
this.__warned = false;
// Define A Proxy for accessing methods easier.
const _this = this;
const _handlerWithOptions = {
get(target, name) {
return (options, ...args) => {
return _this.performCall(name, args, options);
};
},
};
// Define the Proxy without the Options
const _handlerWithoutOptions = {
get(target, name) {
return (...args) => {
return _this.performCall(name, args);
};
},
};
this.methodInterfaceWithOptions = new Proxy({}, _handlerWithOptions);
this.methodInterface = new Proxy({}, _handlerWithoutOptions);
this.services = new mergedData_1.MapBasedMergeData(this._mappingOfDispatchersAndServices, "services/+", "services/+/id");
this.onCancelTask = new index_1.NopeEventEmitter();
if (this._logger) {
this._logger.info("manager created id=", this._id);
}
this.reset();
this._init().catch((error) => {
if (_this._logger) {
_this._logger.error("Failed to intialize the Dispatcher", error);
}
});
(0, gc_1.registerGarbageCallback)(this, this.dispose.bind(this));
}
/**
* Function, which will be called, if an dispatcher is updated.
* This may leads to service that has been removed or added.
* This change emitted on see {@link INopeRpcManager.services}
*
* @author M.Karkowski
* @param {IAvailableServicesMsg} msg The Update Message see {@link IAvailableServicesMsg}
* @memberof NopeRpcManager
*/
updateDispatcher(msg) {
this._mappingOfDispatchersAndServices.set(msg.dispatcher, msg);
this.services.update();
}
/**
* Internal Method to handle the rpcs requests.
*
* @protected
* @param {IRequestRpcMsg} data The provided data of the request
* @param {(...args) => Promise<any>} [_function]
* @return {Promise<void>}
* @memberof NopeRpcManager
*/
async _handleExternalRequest(data, _function = null) {
var _a, _b;
try {
// Try to get the function if not provided:
if (typeof _function !== "function") {
_function = (_a = this._registeredServices.get(data.functionId)) === null || _a === void 0 ? void 0 : _a.func;
}
if ((_b = this._logger) === null || _b === void 0 ? void 0 : _b.enabledFor(index_browser_1.DEBUG)) {
// If there is a Logger:
this._logger.debug(`Dispatcher "${this._id}" received request: "${data.functionId}" -> task: "${data.taskId}"`);
}
const _this = this;
if (typeof _function === "function") {
// Now we check, if we have to perform test, whether
// we are allowed to execute the task:
if (data.target && data.target !== this._id) {
return;
}
// Callbacks
const cbs = [];
const observer = _this.onCancelTask.subscribe((cancelEvent) => {
if (cancelEvent.taskId == data.taskId) {
// Call Every Callback.
cbs.map((cb) => {
return cb(cancelEvent.reason);
});
// Although we are allowed to Cancel the Subscription
observer.unsubscribe();
}
});
// Only if the Function is present extract the arguments etc.
const args = [];
// First extract the basic arguments
data.params.map((item) => {
args[item.idx] = item.data;
});
// Perform the Task it self.
const _resultPromise = _function(...args);
if (typeof (_resultPromise === null || _resultPromise === void 0 ? void 0 : _resultPromise.cancel) === "function") {
// Push the Callback to the Result.
cbs.push((reason) => {
return _resultPromise.cancel(reason);
});
}
// Store, who has requested the task.
_this._runningExternalRequestedTasks.set(data.taskId, data.requestedBy);
let _result = null;
try {
// Wait for the Result to finish.
_result = await _resultPromise;
// Unsubscribe from Task-Cancelation
observer.unsubscribe();
}
catch (error) {
// Unsubscribe from Task-Cancelation
observer.unsubscribe();
// Delte the Task.
_this._runningExternalRequestedTasks.delete(data.taskId);
// Now throw the Error again.
throw error;
}
// Delte the Task.
_this._runningExternalRequestedTasks.delete(data.taskId);
// Define the Result message
const result = {
result: typeof _result !== "undefined" ? _result : null,
taskId: data.taskId,
sink: data.resultSink,
};
// Use the communicator to publish the result.
await this._communicator.emit("rpcResponse", result);
}
}
catch (error) {
if (this._logger) {
// If there is a Logger:
this._logger.error(`Dispatcher "${this._id}" failed with request: "${data.taskId}"`);
this._logger.error(error);
}
// Remove the requested task.
this._runningExternalRequestedTasks.delete(data.taskId);
// An Error occourd => Forward the Error.
const result = {
error: {
error,
msg: error.toString(),
},
taskId: data.taskId,
};
// Send the Error via the communicator to the remote.
await this._communicator.emit("rpcResponse", result);
}
}
/**
* Internal Function to handle responses. In Generale,
* the dispatcher checks if there is an open task with
* the provided id. If so => finish the promise.
*
* @protected
* @param {IRpcResponseMsg} data The Data provided to handle the Response.
* @return {boolean} Returns a boolean, indicating whether a corresponding task was found or not.
* @memberof nopeDispatcher
*/
_handleExternalResponse(data) {
try {
// Extract the Task
const task = this._runningInternalRequestedTasks.get(data.taskId);
// Delete the Task:
this._runningInternalRequestedTasks.delete(data.taskId);
// Based on the Result of the Remote => proceed.
// Either throw an error or forward the result
if (task && data.error) {
if (this._logger) {
this._logger.error(`Failed with task ${data.taskId}`);
this._logger.error(`Reason: ${data.error.msg}`);
this._logger.error(data.error);
}
task.reject(data.error);
// Clearout the Timer
if (task.timeout) {
clearTimeout(task.timeout);
}
return true;
}
if (task) {
task.resolve(data.result);
// Clearout the Timer
if (task.timeout) {
clearTimeout(task.timeout);
}
return true;
}
}
catch (e) {
this._logger.error("Error during handling an external response");
this._logger.error(e);
}
return false;
}
/**
* Function used to update the Available Services.
*
* @protected
* @memberof nopeDispatcher
*/
async _sendAvailableServices() {
var _a;
// Define the Message
const message = {
dispatcher: this._id,
services: Array.from(this._registeredServices.values()).map((item) => {
return item.options;
}),
};
if ((_a = this._logger) === null || _a === void 0 ? void 0 : _a.enabledFor(index_browser_1.DEBUG)) {
this._logger.debug("sending available services");
}
// Send the Message.
await this._communicator.emit("servicesChanged", message);
}
/**
* Internal Function, used to initialize the Dispatcher.
* It subscribes to the "Messages" of the communicator.
*
* @protected
* @memberof nopeDispatcher
*/
async _init() {
const _this = this;
this.ready.setContent(false);
// Wait until the Element is connected.
await this._communicator.connected.waitFor();
await this._connectivityManager.ready.waitFor();
// Subscribe to the availableServices of Remotes.
// If there is a new Service => udpate the External Services
await this._communicator.on("servicesChanged", (data) => {
try {
_this.updateDispatcher(data);
}
catch (e) {
this._logger.error("Error during handling an ServicesChanged");
this._logger.error(e);
}
});
await this._communicator.on("rpcRequest", (data) => {
_this._handleExternalRequest(data);
});
await this._communicator.on("rpcResponse", (data) => {
_this._handleExternalResponse(data);
});
// We will listen on Cancelations.
await this._communicator.on("taskCancelation", (event) => {
if (event.dispatcher === _this._id) {
_this.onCancelTask.emit(event);
}
});
// Now we listen to unregisteredServices
await this._communicator.on("rpcUnregister", (msg) => {
if (_this._registeredServices.has(msg.identifier)) {
_this.unregisterService(msg.identifier);
}
});
await this._communicator.on("bonjour", (msg) => {
if (msg.dispatcherId !== _this._id) {
// If there are dispatchers online,
// We will emit our available services.
_this
._sendAvailableServices()
.then((_) => { })
.catch((e) => {
var _a;
if ((_a = _this._logger) === null || _a === void 0 ? void 0 : _a.enabledFor(index_browser_1.ERROR)) {
// If there is a Logger:
_this._logger.error(`Dispatcher "${_this._id}" failed to emit available services`);
}
});
}
});
// We will use our connecitity-manager to listen to changes.
this._connectivityManager.dispatchers.onChange.subscribe((changes) => {
if (changes.added.length) {
// If there are dispatchers online,
// We will emit our available services.
_this
._sendAvailableServices()
.then((_) => { })
.catch((e) => {
var _a;
if ((_a = _this._logger) === null || _a === void 0 ? void 0 : _a.enabledFor(index_browser_1.ERROR)) {
// If there is a Logger:
_this._logger.error(`Dispatcher "${_this._id}" failed to emit available services`);
}
});
}
if (changes.removed.length) {
// Remove the dispatchers.
changes.removed.map((item) => {
return _this.removeDispatcher(item);
});
}
});
if (this._logger) {
this._logger.info("core.rpc-manager", this._id, "initialized");
}
this.ready.setContent(true);
}
/**
* Helper to remove a dispatcher. This leads to
* closing all open task related to this dispatcher ->
* Exceptions should be thrown. Additional, internal
* task, requested by the dispatcher will be canceled.
*
* @author M.Karkowski
* @param {string} dispatcher
* @memberof NopeRpcManager
*/
removeDispatcher(dispatcher) {
// Delete the Generators of the Instances.
this._mappingOfDispatchersAndServices.delete(dispatcher);
this.services.update();
// Now we need to cancel every Task of the dispatcher,
// which isnt present any more.
this.cancelRunningTasksOfDispatcher(dispatcher, new Error("Dispatcher has been removed! Tasks cannot be executed any more."));
// Stop executing the requested Tasks.
this.cancelRequestedTasksOfDispatcher(dispatcher, new Error("Dispatcher has been removed! Tasks are not required any more."));
}
/**
* Function to cancel an indivual Task. This might be the case, if a
* connection to a specific dispatcher is lost or might have a user-based reason.
*
* @param {string} taskId The Id of the Task. Which should be canceled.
* @param {Error} reason The Reason, why the Task should be canceled (In general shoudl be something meaning full)
* @return {*} Flag, that indicates, whether cancelation was sucessfull or not.
* @memberof nopeDispatcher
*/
async cancelTask(taskId, reason, quiet = false) {
if (this._runningInternalRequestedTasks.has(taskId)) {
const task = this._runningInternalRequestedTasks.get(taskId);
// Delete the task
this._runningInternalRequestedTasks.delete(taskId);
// Propagate the Cancellation (internally):
task.reject(reason);
// Propagate the Cancellation externally.
// Therefore use the desired Mode.
await this._communicator.emit("taskCancelation", {
dispatcher: this._id,
reason,
taskId,
quiet,
});
// Indicate a successful cancelation.
return true;
}
// Task hasnt been found => Cancel the Task.
return false;
}
async _cancelHelper(toCancel, reason) {
if (toCancel.size) {
const promises = [];
for (const taskId of toCancel) {
promises.push(this.cancelTask(taskId, reason));
}
await Promise.all(promises);
}
}
/**
* Helper Function, used to close all tasks with a specific service.
*
* @protected
* @param {string} serviceName The Name of the Service.
* @param {Error} reason The provided Reason, why cancelation is reuqired.
* @memberof nopeDispatcher
*/
async cancelRunningTasksOfService(serviceName, reason) {
// Provide a List containing all Tasks, that has to be canceled
const toCancel = new Set();
// Filter all Tasks that shoud be canceled.
for (const [id, task] of this._runningInternalRequestedTasks.entries()) {
// Therefore compare the reuqired Service by the Task
if (task.serviceName === serviceName) {
// if the service matches, put it to our list.
toCancel.add(id);
}
}
return await this._cancelHelper(toCancel, reason);
}
/**
* Helper to cancel all Tasks which have been requested by a Dispatcher.
*
* @author M.Karkowski
* @param {string} dispatcher
* @param {Error} reason
* @memberof NopeRpcManager
*/
async cancelRequestedTasksOfDispatcher(dispatcher, reason) {
const toCancel = new Set();
for (const [taskId, requestedBy,] of this._runningExternalRequestedTasks.entries()) {
if (requestedBy == dispatcher) {
toCancel.add(taskId);
}
}
return await this._cancelHelper(toCancel, reason);
}
/**
* Cancels all Tasks of the given Dispatcher.
* see {@link NopeRpcManager.cancelTask}
*
* @author M.Karkowski
* @param {string} dispatcher
* @param {Error} reason
* @memberof NopeRpcManager
*/
async cancelRunningTasksOfDispatcher(dispatcher, reason) {
// Provide a List containing all Tasks, that has to be canceled
const toCancel = new Set();
// Filter all Tasks that shoud be canceled.
for (const [id, task] of this._runningInternalRequestedTasks.entries()) {
// Therefore compare the reuqired Service by the Task
if (task.target === dispatcher) {
// if the service matches, put it to our list.
toCancel.add(id);
}
}
return await this._cancelHelper(toCancel, reason);
}
/**
* Function to test if a specific Service exists.
*
* @param {string} id The Id of the Serivce
* @return {boolean} The result of the Test. True if either local or remotly a service is known.
* @memberof nopeDispatcher
*/
serviceExists(id) {
return this.services.amountOf.has(id);
}
/**
* Simple checker, to test, if this rpc-mananger is providing a service with the given id.
*
* @param id The id of the service, which is used during registration
* @return {boolean} The result
*/
isProviding(id) {
return this._registeredServices.has(id);
}
/**
* Function to adapt a Request name.
* Only used internally
*
* @protected
* @param {string} id the original ID
* @return {string} the adapted ID.
* @memberof nopeDispatcher
*/
_getServiceName(id, type) {
return id.startsWith(`${type}/`) ? id : `${type}/${id}`;
}
/**
* Function to unregister a Function from the Dispatcher
* @param {(((...args) => void) | string | number)} func The Function to unregister
* @return {boolean} Flag, whether the element was removed (only if found) or not.
* @memberof nopeDispatcher
*/
async unregisterService(func) {
var _a;
const _id = typeof func === "string"
? this.options.forceUsingValidVarNames
? (0, path_1.varifyPath)(func)
: func
: func.id || "0";
const res = this._registeredServices.delete(_id);
if ((_a = this._logger) === null || _a === void 0 ? void 0 : _a.enabledFor(index_browser_1.DEBUG)) {
// If there is a Logger:
this._logger.debug(`Dispatcher "${this._id}" unregistered: "${_id}"`);
}
// Publish the Available Services.
await this._sendAvailableServices();
return res;
}
adaptServiceId(name) {
if (name.startsWith(`nope${objectMethods_1.SPLITCHAR}service${objectMethods_1.SPLITCHAR}`)) {
return name;
}
return `nope${objectMethods_1.SPLITCHAR}service${objectMethods_1.SPLITCHAR}${name}`;
}
/**
* Function to register a Function in the Dispatcher
*
* @param {(...args) => Promise<any>} func The function which should be called if a request is mapped to the Function.
* @param {{
* // Flag to enable unregistering the function after calling.
* deleteAfterCalling?: boolean,
* // Instead of generating a uuid an id could be provided
* id?: string;
* }} [options={}] Options to enhance the registered ID and enabling unregistering the Element after calling it.
* @return {(...args) => Promise<any>} The registered Function
* @memberof nopeDispatcher
*/
async registerService(func, options) {
var _a;
const _this = this;
// Define / Use the ID of the Function.
let _id = options.id || (0, idMethods_1.generateId)();
_id = options.addNopeServiceIdPrefix ? this.adaptServiceId(_id) : _id;
_id = this.options.forceUsingValidVarNames ? (0, path_1.varifyPath)(_id) : _id;
// Make shure we assign our id
options.id = _id;
if (this.isProviding(options.id) &&
this._registeredServices.get(options.id).func != func) {
const err = Error(`The service "${_id}" is already declared!`);
this._logger.error(`The service "${_id}" is already declared!`);
this._logger.error(err);
throw err;
}
let _func = func;
if (!this.__warned && !(0, async_1.isAsyncFunction)(func) && this._logger) {
this._logger.warn("!!! You have provided synchronous functions. They may break NoPE. Use them with care !!!");
this._logger.warn(`The service "${_id}" is synchronous!`);
this.__warned = true;
}
// Define a ID for the Function
_func.id = _id;
// Define the callback.
_func.unregister = () => {
return _this.unregisterService(_id);
};
// Register the Function
this._registeredServices.set(_func.id, {
options: options,
func: _func,
});
// Publish the Available Services.
await this._sendAvailableServices();
if ((_a = this._logger) === null || _a === void 0 ? void 0 : _a.enabledFor(index_browser_1.DEBUG)) {
// If there is a Logger:
this._logger.debug(`Dispatcher "${this._id}" registered: "${_id}"`);
}
// Return the Function.
return _func;
}
/**
* Function which is used to perform a call on the remote.
*
* @author M.Karkowski
* @template T
* @param {string} serviceName serviceName The Name / ID of the Function
* @param {any[]} params
* @param {(Partial<ICallOptions> & {
* selector?: ValidSelectorFunction;
* quiet?: boolean;
* })} [options={}] Options for the Call. You can assign a different selector.
* @return {*} {INopePromise<T>} The result of the call
* @memberof nopeDispatcher
*/
_performCall(serviceName, params, options = {}) {
var _a;
// Our implemented Shortcut to speed things up.
if (this.services.amountOf.get(serviceName) === 1 &&
this._registeredServices.has(serviceName)) {
const func = this._registeredServices.get(serviceName).func;
const perhapsPromise = func(...params);
const isAsync = (0, async_1.isAsyncFunction)(func);
// Define a simple promise.
const ret = new nopePromise_1.NopePromise((resolve, reject) => {
if (options.timeout > 0) {
setTimeout(reject, options.timeout, new Error(`TIMEOUT. The Service allowed execution time of ${options.timeout.toString()}[ms] has been excided`));
}
if (!isAsync) {
resolve(perhapsPromise);
}
else {
perhapsPromise.then(resolve).catch(reject);
}
});
// Assign the cancel function.
ret.cancel = (reason) => {
if (isAsync &&
typeof perhapsPromise.cancel == "function") {
perhapsPromise.cancel(reason);
}
};
return ret;
}
// Get a Call Id
const _taskId = (0, idMethods_1.generateId)();
const _this = this;
const _options = {
resultSink: this._getServiceName(serviceName, "response"),
...options,
};
const clear = () => {
// Remove the task:
if (_this._runningInternalRequestedTasks.has(_taskId)) {
const task = _this._runningInternalRequestedTasks.get(_taskId);
// Remove the Timeout.
if (task.timeout) {
clearTimeout(task.timeout);
}
// Remove the Task itself
_this._runningInternalRequestedTasks.delete(_taskId);
}
};
if ((_a = _this._logger) === null || _a === void 0 ? void 0 : _a.enabledFor(index_browser_1.DEBUG)) {
_this._logger.debug(`Dispatcher "${this._id}" requesting externally Function "${serviceName}" with task: "${_taskId}"`);
}
// Define a Callback-Function, which will expect the Task.
const ret = new nopePromise_1.NopePromise(async (resolve, reject) => {
var _a;
try {
const taskRequest = {
resolve,
reject,
clear,
serviceName,
timeout: null,
target: null,
};
// Register the Handlers,
_this._runningInternalRequestedTasks.set(_taskId, taskRequest);
// Define a Task-Request
const packet = {
functionId: serviceName,
params: [],
taskId: _taskId,
resultSink: _options.resultSink,
requestedBy: _this._id,
};
for (const [idx, contentOfParameter] of params.entries()) {
packet.params.push({
idx,
data: contentOfParameter,
});
}
if (!_this.serviceExists(serviceName)) {
// Create an Error:
const error = new Error(`No Service Provider known for "${serviceName}"`);
if (_this._logger) {
_this._logger.error(`No Service Provider known for "${serviceName}"`);
_this._logger.error(error);
}
throw error;
}
if (_this.options.forceUsingSelectors ||
this.services.amountOf.get(serviceName) > 1) {
// Fixing the Selection
if (typeof options.target === "string") {
taskRequest.target = options.target;
}
else if (typeof (options === null || options === void 0 ? void 0 : options.selector) === "function") {
const dispatcherToUse = await options.selector({
rpcManager: this,
serviceName,
});
// Assign the Selector:
taskRequest.target = dispatcherToUse;
}
else {
const dispatcherToUse = await this._defaultSelector({
rpcManager: this,
serviceName,
});
// Assign the Selector:
taskRequest.target = dispatcherToUse;
}
packet.target = taskRequest.target;
}
else {
taskRequest.target = Array.from(this.services.keyMappingReverse.get(serviceName))[0];
}
// Send the Message to the specific element:
await _this._communicator.emit("rpcRequest", packet);
if ((_a = _this._logger) === null || _a === void 0 ? void 0 : _a.enabledFor(index_browser_1.DEBUG)) {
_this._logger.debug(`Dispatcher "${this._id}" putting task "${_taskId}" on: "${_this._getServiceName(packet.functionId, "request")}"`);
}
// If there is a timeout =>
if (options.timeout > 0) {
taskRequest.timeout = setTimeout(() => {
_this
.cancelTask(_taskId, new Error(`TIMEOUT. The Service allowed execution time of ${options.timeout.toString()}[ms] has been excided`), false)
.catch((e) => {
_this._logger.error(`Failed to cancel the task ${_taskId}.`);
});
}, options.timeout);
}
}
catch (e) {
// Clear all Elements of the Function:
clear();
// Throw the error.
reject(e);
}
});
ret.taskId = _taskId;
ret.cancel = (reason) => {
_this.cancelTask(_taskId, reason);
};
return ret;
}
/**
* Function which is used to perform a call on the remote.
* Please see {@link INopeRpcManager.performCall} for more Info.
*/
performCall(serviceName, params, options) {
if (Array.isArray(serviceName)) {
if (Array.isArray(options) && options.length !== serviceName.length) {
throw Error("Array Length must match.");
}
const promises = serviceName.map((service, idx) => {
return this._performCall(service, params, Array.isArray(options) ? options[idx] : options);
});
return Promise.all(promises);
}
else {
if (Array.isArray(options)) {
// Throw an error.
throw Error("Expecting a single Value for the options");
}
return this._performCall(serviceName, params, options);
}
}
/**
* Function to clear all pending tasks
*
* @memberof nopeDispatcher
*/
clearTasks() {
if (this._runningInternalRequestedTasks) {
this._runningInternalRequestedTasks.clear();
}
else
this._runningInternalRequestedTasks = new Map();
}
/**
* Function to unregister all Functions of the Dispatcher.
*
* @memberof nopeDispatcher
*/
unregisterAll() {
if (this._registeredServices) {
const toUnregister = Array.from(this._registeredServices.keys());
for (const id of toUnregister) {
this.unregisterService(id);
}
this._registeredServices.clear();
}
else {
this._registeredServices = new Map();
}
}
/**
* Function to reset the Dispatcher.
*
* @memberof nopeDispatcher
*/
reset() {
this.clearTasks();
this.unregisterAll();
this._mappingOfDispatchersAndServices = new Map();
this.services.update(this._mappingOfDispatchersAndServices);
this._runningExternalRequestedTasks = new Map();
}
async dispose() {
this.clearTasks();
this.unregisterAll();
}
/**
* Describes the Data.
* @returns
*/
toDescription() {
const ret = {
services: {
all: this.services.data.getContent(),
internal: Array.from(this._registeredServices.values()),
},
task: {
executing: Array.from(this._runningExternalRequestedTasks.values()),
requested: Array.from(this._runningInternalRequestedTasks.entries()).map((item) => {
return {
id: item[0],
service: item[1].serviceName,
target: item[1].target,
timeout: item[1].timeout,
};
}),
},
};
return ret;
}
}
exports.NopeRpcManager = NopeRpcManager;