UNPKG

bpmn-elements

Version:

Executable workflow elements based on BPMN 2.0

255 lines (254 loc) 7.54 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = IoSpecification; var _getPropertyValue = _interopRequireDefault(require("../getPropertyValue.js")); var _shared = require("../shared.js"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const kConsuming = Symbol.for('consuming'); function IoSpecification(activity, ioSpecificationDef, context) { const { id, type = 'iospecification', behaviour = {} } = ioSpecificationDef; this.id = id; this.type = type; this.behaviour = behaviour; this.activity = activity; this.broker = activity.broker; this.context = context; } IoSpecification.prototype.activate = function activate(message) { if (this[kConsuming]) return; if (message?.fields.redelivered && message.fields.routingKey === 'run.start') { this._onFormatEnter(); } if (message?.fields.redelivered && message.fields.routingKey === 'run.end') { this._onFormatComplete(message); } this[kConsuming] = this.broker.subscribeTmp('event', 'activity.#', this._onActivityEvent.bind(this), { noAck: true }); }; IoSpecification.prototype.deactivate = function deactivate() { if (this[kConsuming]) this[kConsuming] = this[kConsuming].cancel(); }; IoSpecification.prototype._onActivityEvent = function onActivityEvent(routingKey, message) { const { dataInputs, dataOutputs } = this.behaviour; if ((dataInputs || dataOutputs) && routingKey === 'activity.enter') { return this._onFormatEnter(); } if (dataOutputs && routingKey === 'activity.execution.completed') { this._onFormatComplete(message); } }; IoSpecification.prototype._onFormatEnter = function onFormatOnEnter() { const safeType = (0, _shared.brokerSafeId)(this.type).toLowerCase(); const startRoutingKey = `run.onstart.${safeType}`; const { dataInputs, dataOutputs } = this.behaviour; const broker = this.broker; if (!dataInputs) { return broker.publish('format', startRoutingKey, { ioSpecification: { dataOutputs: this._getDataOutputs(dataOutputs) } }); } const { dataObjects, sources } = dataInputs.reduce((result, ioSource, index) => { const source = { id: ioSource.id, type: ioSource.type, name: ioSource.name }; result.sources.push(source); const dataObjectId = (0, _getPropertyValue.default)(ioSource, 'behaviour.association.source.dataObject.id'); if (!dataObjectId) return result; const dataObject = this.context.getDataObjectById(dataObjectId); if (!dataObject) return result; result.dataObjects.push({ index, dataObject }); return result; }, { dataObjects: [], sources: [] }); if (!dataObjects.length) { return broker.publish('format', startRoutingKey, { ioSpecification: { dataInputs: sources, dataOutputs: this._getDataOutputs(dataOutputs) } }); } const endRoutingKey = `run.onstart.${safeType}.end`; broker.publish('format', `${startRoutingKey}.begin`, { endRoutingKey, ioSpecification: { dataInputs: sources.map(source => { return { ...source }; }), dataOutputs: this._getDataOutputs(dataOutputs) } }); return read(broker, dataObjects, (_, responses) => { for (const response of responses) sources[response.index].value = response.value; broker.publish('format', endRoutingKey, { ioSpecification: { dataInputs: sources, dataOutputs: this._getDataOutputs(dataOutputs) } }); }); }; IoSpecification.prototype._onFormatComplete = function formatOnComplete(message) { const safeType = (0, _shared.brokerSafeId)(this.type).toLowerCase(); const messageInputs = (0, _getPropertyValue.default)(message, 'content.ioSpecification.dataInputs'); const messageOutputs = (0, _getPropertyValue.default)(message, 'content.output.ioSpecification.dataOutputs') || []; const dataOutputs = this.behaviour.dataOutputs; const broker = this.broker; const context = this.context; const { dataObjects, sources } = dataOutputs.reduce((result, ioSource, index) => { const { value } = messageOutputs.find(output => output.id === ioSource.id) || {}; const source = { id: ioSource.id, type: ioSource.type, name: ioSource.name, value }; result.sources.push(source); const dataObjectId = (0, _getPropertyValue.default)(ioSource, 'behaviour.association.target.dataObject.id'); if (!dataObjectId) return result; const dataObject = context.getDataObjectById(dataObjectId); if (!dataObject) return result; result.dataObjects.push({ index, dataObject, value }); return result; }, { dataObjects: [], sources: [] }); const startRoutingKey = `run.onend.${safeType}`; if (!dataObjects.length) { return broker.publish('format', startRoutingKey, { ioSpecification: { dataInputs: messageInputs, dataOutputs: sources } }); } const endRoutingKey = `run.onend.${safeType}.end`; broker.publish('format', `${startRoutingKey}.begin`, { endRoutingKey, ioSpecification: { ...(messageInputs && { dataInputs: messageInputs.map(input => { return { ...input }; }) }), dataOutputs: this._getDataOutputs(dataOutputs) } }); return write(broker, dataObjects, (_, responses) => { for (const response of responses) sources[response.index].value = response.value; broker.publish('format', endRoutingKey, { ioSpecification: { ...(messageInputs && { dataInputs: messageInputs.map(input => { return { ...input }; }) }), dataOutputs: sources } }); }); }; IoSpecification.prototype._getDataOutputs = function getDataOutputs(dataOutputs) { if (!dataOutputs) return; return dataOutputs.map(dataOutput => { return { id: dataOutput.id, type: dataOutput.type, name: dataOutput.name }; }); }; function read(broker, dataObjectRefs, callback) { const responses = []; let count = 0; const dataReadConsumer = broker.subscribeTmp('data', 'data.read.#', onDataObjectResponse, { noAck: true }); for (const { dataObject } of dataObjectRefs) { dataObject.read(broker, 'data', 'data.read.'); } function onDataObjectResponse(routingKey, message) { const { index } = dataObjectRefs.find(({ dataObject }) => dataObject.id === message.content.id); responses.push({ ...message.content, index }); ++count; if (count < dataObjectRefs.length) return; dataReadConsumer.cancel(); return callback(null, responses); } } function write(broker, dataObjectRefs, callback) { const responses = []; let count = 0; broker.subscribeTmp('data', 'data.write.#', onDataObjectResponse, { noAck: true }); for (const { dataObject, value } of dataObjectRefs) { dataObject.write(broker, 'data', 'data.write.', value); } function onDataObjectResponse(routingKey, message) { const idx = dataObjectRefs.findIndex(({ dataObject }) => dataObject.id === message.content.id); responses[idx] = { index: idx, ...message.content }; ++count; if (count < dataObjectRefs.length) return; broker.cancel(message.fields.consumerTag); return callback(null, responses); } }