UNPKG

@just-in/core

Version:

A TypeScript-first framework for building adaptive digital health interventions.

211 lines 9.17 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.setShouldProcessQueue = exports.startEventQueueProcessing = exports.stopEventQueueProcessing = exports.setupEventQueueListener = exports.processEventQueue = exports.publishEvent = void 0; exports.isRunning = isRunning; exports.queueIsEmpty = queueIsEmpty; const change_listener_manager_1 = require("../data-manager/change-listener.manager"); const data_manager_1 = __importDefault(require("../data-manager/data-manager")); const user_manager_1 = require("../user-manager/user-manager"); const data_manager_constants_1 = require("../data-manager/data-manager.constants"); const logger_manager_1 = require("../logger/logger-manager"); const task_manager_1 = require("../handlers/task.manager"); const decision_rule_manager_1 = require("../handlers/decision-rule.manager"); const data_manager_type_1 = require("../data-manager/data-manager.type"); const event_handler_manager_1 = require("./event-handler-manager"); const event_executor_1 = require("./event-executor"); const dataManager = data_manager_1.default.getInstance(); const clm = change_listener_manager_1.ChangeListenerManager.getInstance(); const eventHandlerManager = event_handler_manager_1.EventHandlerManager.getInstance(); let isProcessingQueue = false; let shouldProcessQueue = true; /** * Triggers an event by creating an instance in the `EVENTS_QUEUE`. */ const publishEvent = async (eventType, generatedTimestamp, eventDetails) => { try { if (!eventHandlerManager.hasHandlersForEventType(eventType)) { logger_manager_1.Log.warn(`No handlers found for event type "${eventType}". Skipping event publication.`); return; } const eventInstance = { eventType, generatedTimestamp, publishedTimestamp: new Date(), eventDetails, }; const addedEvent = await dataManager.addItemToCollection(data_manager_constants_1.EVENT_QUEUE, eventInstance); logger_manager_1.Log.info(`Published event "${eventInstance.eventType}" with ID: ${addedEvent.id}.`); } catch (error) { logger_manager_1.Log.error(`Failed to publish event "${eventType}": ${error}`); throw error; } }; exports.publishEvent = publishEvent; /** * Processes events in the `EVENTS_QUEUE`. */ const processEventQueue = async () => { if (isProcessingQueue) { logger_manager_1.Log.info('Event queue processing already in progress. Skipping processing.'); return; } isProcessingQueue = true; try { logger_manager_1.Log.dev('Starting event queue processing.'); while (shouldProcessQueue) { const users = user_manager_1.UserManager.getAllUsers(); const events = (await dataManager.getAllInCollection(data_manager_constants_1.EVENT_QUEUE)); if (!events || events.length === 0) { logger_manager_1.Log.dev('No events left in the queue. Pausing processing.'); break; } for (const event of events) { logger_manager_1.Log.dev(`Processing event "${event.eventType}" with ID: ${event.id} for ${users.length} users.`); await (0, event_executor_1.executeEventForUsers)(event, users, eventHandlerManager); try { await archiveEvent(event); } catch (error) { logger_manager_1.Log.error(`Failed to archive event "${event.eventType}" with ID: ${event.id}: ${error}`); } } } logger_manager_1.Log.dev('Finished processing event queue.'); } catch (error) { logger_manager_1.Log.error(`Error during event queue processing: ${error}`); } finally { isProcessingQueue = false; } }; exports.processEventQueue = processEventQueue; /** * Sets up a listener for the `EVENTS_QUEUE` collection. */ const setupEventQueueListener = async () => { try { logger_manager_1.Log.dev('Setting up event queue listener.'); if (clm.hasChangeListener(data_manager_constants_1.EVENT_QUEUE, data_manager_type_1.CollectionChangeType.INSERT)) { logger_manager_1.Log.info('Event queue listener already set up. Skipping setup.'); return; } clm.addChangeListener(data_manager_constants_1.EVENT_QUEUE, data_manager_type_1.CollectionChangeType.INSERT, async () => { if (shouldProcessQueue) { logger_manager_1.Log.dev('New event detected in EVENTS_QUEUE. Triggering processing.'); await (0, exports.processEventQueue)(); } }); await (0, exports.processEventQueue)(); logger_manager_1.Log.dev('Event queue listener set up successfully.'); } catch (error) { logger_manager_1.Log.error(`Error setting up event queue listener: ${error}`); } }; exports.setupEventQueueListener = setupEventQueueListener; /** * Processes assignments (tasks or decision rules) for an event and user. */ const processHandlers = async (event, user) => { for (const handlerName of eventHandlerManager.getHandlersForEventType(event.eventType)) { try { const task = (0, task_manager_1.getTaskByName)(handlerName); if (task) { await (0, task_manager_1.executeTask)(task, event, user); continue; } const decisionRule = (0, decision_rule_manager_1.getDecisionRuleByName)(handlerName); if (decisionRule) { await (0, decision_rule_manager_1.executeDecisionRule)(decisionRule, event, user); continue; } logger_manager_1.Log.warn(`Handler "${handlerName}" not found for event "${event.eventType}".`); } catch (error) { logger_manager_1.Log.error(`Error processing assignment "${handlerName}" for event "${event.eventType}" and user "${user.id}": ${error}`); } } }; const processExecutionLifecycle = async (handlerName, event, functionName) => { try { const task = (0, task_manager_1.getTaskByName)(handlerName); if (task && typeof task[functionName] === "function") { await task[functionName](event); return; } const decisionRule = (0, decision_rule_manager_1.getDecisionRuleByName)(handlerName); if (decisionRule && typeof decisionRule[functionName] === "function") { await decisionRule[functionName](event); return; } // Log warning if function is not found logger_manager_1.Log.dev(`"${functionName}" not found for handler "${handlerName}".`); } catch (error) { logger_manager_1.Log.error(`Error executing "${functionName}" for handler "${handlerName}" and event "${event.eventType}": ${error}`); } }; /** * Archives a processed event by moving it from `EVENTS_QUEUE` to `ARCHIVED_EVENTS`. */ const archiveEvent = async (event) => { try { logger_manager_1.Log.dev(`Archiving event of type "${event.eventType}" with ID: ${event.id}.`); await dataManager.addItemToCollection(data_manager_constants_1.ARCHIVED_EVENTS, event); if (event.id) { await dataManager.removeItemFromCollection(data_manager_constants_1.EVENT_QUEUE, event.id); } else { logger_manager_1.Log.error(`Event "${event}" has no ID. Skipping archiving.`); } logger_manager_1.Log.dev(`Event of type "${event.eventType}" with ID: ${event.id} archived successfully.`); } catch (error) { logger_manager_1.Log.error(`Failed to archive event "${event.eventType}" with ID: ${event.id}: ${error}`); throw error; } }; /** * Stops the event queue processing. */ const stopEventQueueProcessing = () => { shouldProcessQueue = false; clm.removeChangeListener(data_manager_constants_1.EVENT_QUEUE, data_manager_type_1.CollectionChangeType.INSERT); logger_manager_1.Log.info('Event queue processing stopped.'); }; exports.stopEventQueueProcessing = stopEventQueueProcessing; /** * Starts the event queue processing. */ const startEventQueueProcessing = async () => { await (0, exports.setupEventQueueListener)(); shouldProcessQueue = true; logger_manager_1.Log.dev('Event queue processing started.'); }; exports.startEventQueueProcessing = startEventQueueProcessing; /** * Returns true if the event queue is running. */ function isRunning() { return shouldProcessQueue; } /** * Returns true if the event queue is empty. */ async function queueIsEmpty() { const events = await dataManager.getAllInCollection(data_manager_constants_1.EVENT_QUEUE); return !events || events.length === 0; } /** * Sets the shouldProcessQueue flag. */ const setShouldProcessQueue = (shouldProcess) => { shouldProcessQueue = shouldProcess; }; exports.setShouldProcessQueue = setShouldProcessQueue; //# sourceMappingURL=event-queue.js.map