UNPKG

@5minds/processcube_engine

Version:

The ProcessCube Engine. Stores and executes BPMNs.

179 lines • 7.66 kB
"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 __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