@5minds/processcube_engine
Version:
The ProcessCube Engine. Stores and executes BPMNs.
179 lines • 7.66 kB
JavaScript
;
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 __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 __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.EventAggregator = void 0;
const dayjs_1 = __importDefault(require("dayjs"));
const uuid = __importStar(require("uuid"));
const processcube_engine_sdk_1 = require("@5minds/processcube_engine_sdk");
const logger = new processcube_engine_sdk_1.Logger('event_aggregator');
const eventSubscriptionDictionary = {};
const acknowledgeDictionary = {};
function subscribe(eventName, callback) {
logger.trace(`Create Event Aggregator "subscribe" subscription: ${eventName}`);
return createSubscription(eventName, callback, false);
}
function subscribeOnce(eventName, callback) {
logger.trace(`Create Event Aggregator "subscribeOnce" subscription: ${eventName}`);
return createSubscription(eventName, callback, true);
}
function publish(eventName, payload, onAcknowledgement, eventId) {
const publishStart = (0, dayjs_1.default)();
const eventIdToUse = eventId ?? uuid.v4();
logger.trace(`Publishing Event Aggregator event: ${eventName} with Event ID: ${eventIdToUse} (${onAcknowledgement != null ? 'awaiting acknowledgement' : 'no acknowledgement awaited'})`);
payload = payload ?? {};
payload.eventId = eventIdToUse;
const eventSubscriptions = {
...eventSubscriptionDictionary[eventName],
};
const noSubscribersForEventExist = !eventSubscriptions || Object.keys(eventSubscriptions).length === 0;
if (noSubscribersForEventExist) {
logger.trace(`No subscribers for event: ${eventName} found.`);
if (onAcknowledgement) {
setImmediate(() => {
onAcknowledgement();
});
}
return;
}
const subscriptionIds = Object.keys(eventSubscriptions);
logger.trace(`Publishing event ${eventName} (Event ID: ${eventIdToUse}) to ${subscriptionIds.length} subscribers.`);
if (onAcknowledgement) {
logger.trace(`Awaiting acknowledgement for event ${eventName} (Event ID: ${eventIdToUse}) from ${subscriptionIds.length} subscribers.`);
acknowledgeDictionary[eventIdToUse] = {
currentAckCount: 0,
estimatedAckCount: subscriptionIds.length,
callback: onAcknowledgement,
};
}
for (const subscriptionId of subscriptionIds) {
logger.trace(`Publishing event ${eventName} (Event ID: ${eventIdToUse}) to subscriber ${subscriptionId}.`);
const subscription = eventSubscriptions[subscriptionId];
invokeEventCallback(eventName, payload, subscription.callback);
if (subscription.subscribeOnce) {
removeSubscription(eventName, subscriptionId);
}
}
const durationInMiliseconds = Math.floor(dayjs_1.default.duration((0, dayjs_1.default)().diff(publishStart)).asMilliseconds());
logger.trace(`Publishing event ${eventName} (Event ID: ${eventIdToUse}) to ${subscriptionIds.length} subscribers finished after ${durationInMiliseconds}ms.`);
}
function acknowledgeEvent(eventId) {
logger.trace(`A receiver acknowledged receit of event ${eventId}.`);
if (!eventId || !acknowledgeDictionary[eventId]) {
return;
}
const ackData = acknowledgeDictionary[eventId];
if (++ackData.currentAckCount >= ackData.estimatedAckCount) {
logger.trace(`All subscribers have acknowledged Event ${eventId}. Done!`);
setImmediate(() => {
ackData.callback();
});
delete acknowledgeDictionary[eventId];
}
logger.trace(`Estimated Acknowledgements for ${eventId} remaining: ${ackData.estimatedAckCount - ackData.currentAckCount}`);
}
function unsubscribe(subscription) {
if (!subscription) {
return;
}
logger.trace(`Removing Subscription "${subscription.id}" from event ${subscription.eventName}`);
removeSubscription(subscription.eventName, subscription.id);
}
function clear() {
Object.keys(eventSubscriptionDictionary).forEach((key) => delete eventSubscriptionDictionary[key]);
}
function createSubscription(event, callback, oneTimeSubscription) {
if (!event) {
throw new processcube_engine_sdk_1.BadRequestError('No event name provided for the subscription!');
}
if (!callback) {
throw new processcube_engine_sdk_1.BadRequestError('No callback function provided for the subscription!');
}
const subscriptionId = uuid.v4();
const newSubscription = {
id: subscriptionId,
eventName: event,
onlyReceiveOnce: oneTimeSubscription,
};
Object.freeze(newSubscription);
const eventIsNotYetRegistered = !eventSubscriptionDictionary[event];
if (eventIsNotYetRegistered) {
eventSubscriptionDictionary[event] = {};
}
eventSubscriptionDictionary[event][subscriptionId] = {
subscribeOnce: oneTimeSubscription,
callback: callback,
};
logger.trace(`Currently registered subscribers for event ${event}: ${Object.keys(eventSubscriptionDictionary[event]).length}`);
return newSubscription;
}
function invokeEventCallback(eventName, eventPayload, callback) {
setImmediate(() => {
try {
callback(eventPayload, eventName);
}
catch (error) {
logger.warn(error.message, {
err: error,
});
}
});
}
function removeSubscription(eventName, subscriptionId) {
if (!eventName || !subscriptionId || !eventSubscriptionDictionary[eventName]) {
return;
}
delete eventSubscriptionDictionary[eventName][subscriptionId];
if (Object.keys(eventSubscriptionDictionary[eventName]).length == 0) {
delete eventSubscriptionDictionary[eventName];
}
}
exports.EventAggregator = {
acknowledgeEvent: acknowledgeEvent,
subscribe: subscribe,
subscribeOnce: subscribeOnce,
publish: publish,
unsubscribe: unsubscribe,
/**
* Clears all subscriptions currently registered on the Event Aggregator.
*
* CAUTION - Use this only for cleanup procedures during shutdown. DO NOT use this during normal operations!
*/
clear_UNSAFE: clear,
};
exports.default = exports.EventAggregator;
//# sourceMappingURL=EventAggregator.js.map