@5minds/processcube_engine
Version:
The ProcessCube Engine. Stores and executes BPMNs.
247 lines • 11.2 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ServiceFacade = void 0;
const diagnostics_channel = __importStar(require("diagnostics_channel"));
const inversify_1 = require("inversify");
const uuid = __importStar(require("uuid"));
const processcube_engine_sdk_1 = require("@5minds/processcube_engine_sdk");
const CancellationToken_1 = require("../Api/CancellationToken");
const Contracts_1 = require("../Contracts");
const Tools_1 = require("../Tools");
const MonitoringManager_1 = require("../Tools/MonitoringManager");
const WorkerMessages_1 = require("./WorkerMessages");
let ServiceFacade = class ServiceFacade {
registeredServiceFunctions = {};
serviceSubscriptions = {};
cancellationTokens = {};
logger;
bootstrapper;
functionReportChannelSubscription = (functionReport) => {
this.reportFunction(functionReport);
};
constructor(container) {
this.bootstrapper = new Tools_1.Bootstrapper(container);
this.logger = new processcube_engine_sdk_1.Logger('engine:service_facade');
process.on('message', this.onMessageReceived.bind(this));
diagnostics_channel.subscribe(MonitoringManager_1.FUNCTION_REPORTS_CHANNEL_NAME, this.functionReportChannelSubscription);
}
async init() {
try {
await this.bootstrapper.start();
this.logger.trace('Bootstrapper started successfully.');
}
catch (error) {
this.logger.error('Bootstrapper failed to start.', {
err: error,
});
process.exit(1);
}
}
registerServiceFunction(topic, handler, isCancelable = false) {
this.registeredServiceFunctions[topic] = {
handler: handler,
isCancelable: isCancelable,
};
}
emitStartupFinishedMessage() {
const startupFinishedMessage = {
id: uuid.v4(),
type: 'StartupFinishedMessage',
};
this.serializeAndSend(startupFinishedMessage);
}
async onMessageReceived(message) {
const deserializedMessage = (0, WorkerMessages_1.deserializeWorkerMessage)(message);
if (!deserializedMessage || !deserializedMessage.id || !deserializedMessage.type) {
this.logger.warn('Unable to dispatch runtime message - message is either undefined or has no id or type.', { workerMessage: deserializedMessage });
return;
}
switch (deserializedMessage.type) {
case 'FunctionRequestMessage':
return this.handleFunctionRequestMessage(deserializedMessage);
case 'SubscriptionRequestMessage':
return this.handleSubscriptionRequestMessage(deserializedMessage);
case 'SubscriptionCancellationMessage':
return this.handleSubscriptionCancellationMessage(deserializedMessage);
case 'FunctionCancellationMessage':
return this.handleFunctionCancellationMessage(deserializedMessage);
case 'EventNotificationMessage':
return this.handleEventNotificationMessage(deserializedMessage);
case 'GracefulShutdownMessage':
return this.handleGracefullyShutdownMessage();
default:
this.logger.warn('Unable to dispatch runtime message - message type is not known.', { workerMessage: deserializedMessage });
}
}
handleEventNotificationMessage(message) {
Tools_1.EventAggregator.publish(message.topic, message.payload);
}
async handleFunctionRequestMessage(message) {
const service = this.registeredServiceFunctions[message.topic];
const resultMessage = {
id: message.id,
type: 'FunctionResponseMessage',
};
if (!service) {
const dispatchError = new Error(`Unable to dispatch message - no service with topic \`${message.topic}\` found.`);
this.logger.error('Message dispatch failed.', { err: dispatchError, workerMessage: message });
resultMessage.error = dispatchError;
this.serializeAndSend(resultMessage);
return;
}
try {
let result;
if (service.isCancelable) {
this.logger.trace('Generating CancellationToken for cancelable service function.', { workerMessage: message });
const cancellationToken = new CancellationToken_1.CancellationToken();
this.cancellationTokens[message.id] = cancellationToken;
result = await service.handler(...message.payload, cancellationToken);
}
else {
result = await service.handler(...message.payload);
}
resultMessage.payload = result;
}
catch (error) {
resultMessage.error = error;
}
if (this.cancellationTokens[message.id]) {
delete this.cancellationTokens[message.id];
}
this.serializeAndSend(resultMessage);
}
reportFunction(functionReport) {
const metricsMessage = {
id: uuid.v4(),
type: 'MetricsMessage',
typeOfMetrics: 'FunctionReport',
payload: functionReport,
};
this.serializeAndSend(metricsMessage);
}
async handleSubscriptionRequestMessage(message) {
const serviceFunction = this.registeredServiceFunctions[message.topic];
const resultMessage = {
id: message.id,
type: 'SubscriptionResponseMessage',
};
if (!serviceFunction) {
const dispatchError = new Error(`Unable to dispatch message - no service with topic \`${message.topic}\` found.`);
this.logger.error('Message dispatch failed.', { err: dispatchError, workerMessage: message });
resultMessage.error = dispatchError;
this.serializeAndSend(resultMessage);
return;
}
try {
const subscriptionFunction = this.emitSubscriptionEvent.bind(this, message.id, message.topic, message.subscribeOnce);
await serviceFunction.handler(subscriptionFunction, message.subscribeOnce, ...message.payload);
const unsubscribe = Tools_1.EventAggregator.unsubscribe.bind(Tools_1.EventAggregator, subscriptionFunction);
this.serviceSubscriptions[message.id] = {
emitEvent: subscriptionFunction,
unsubscribe: unsubscribe,
subscribeOnce: message.subscribeOnce,
};
}
catch (error) {
resultMessage.error = error;
}
this.serializeAndSend(resultMessage);
}
serializeAndSend(message) {
const serializedMessage = (0, WorkerMessages_1.serializeWorkerMessage)(message);
process.send(serializedMessage);
}
handleSubscriptionCancellationMessage(message) {
const serviceSubscription = this.serviceSubscriptions[message.id];
if (!serviceSubscription) {
this.logger.error('Unable to dispatch subscription cancellation message - no service with a matching topic found.', { workerMessage: message });
return;
}
delete this.serviceSubscriptions[message.id];
serviceSubscription.unsubscribe();
}
async handleFunctionCancellationMessage(message) {
const cancellationToken = this.cancellationTokens[message.id];
if (!cancellationToken) {
this.logger.trace('Unable to dispatch function cancellation message - no cancellationToken with a matching id found.', { workerMessage: message });
return;
}
delete this.cancellationTokens[message.id];
await cancellationToken.cancel();
}
emitSubscriptionEvent(id, topic, subscribeOnce, payload) {
const eventMessage = {
id: id,
type: 'SubscriptionEventMessage',
topic: topic,
payload: payload,
};
if (subscribeOnce) {
delete this.serviceSubscriptions[id];
}
this.serializeAndSend(eventMessage);
}
async handleGracefullyShutdownMessage() {
this.logger.trace('Gracefully exiting worker...');
await this.dispose();
process.exit(0);
}
async dispose() {
if (this.functionReportChannelSubscription) {
diagnostics_channel.unsubscribe(MonitoringManager_1.FUNCTION_REPORTS_CHANNEL_NAME, this.functionReportChannelSubscription);
}
await this.bootstrapper.stop();
}
};
exports.ServiceFacade = ServiceFacade;
exports.ServiceFacade = ServiceFacade = __decorate([
(0, inversify_1.injectable)(),
__param(0, (0, inversify_1.inject)(Contracts_1.IocRegistrationKeys.internal.Container)),
__metadata("design:paramtypes", [inversify_1.Container])
], ServiceFacade);
//# sourceMappingURL=ServiceFacade.js.map