@just-in/core
Version:
A TypeScript-first framework for building adaptive digital health interventions.
223 lines • 9.82 kB
JavaScript
;
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 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.`);
for (const handlerName of eventHandlerManager.getHandlersForEventType(event.eventType)) {
await processExecutionLifecycle(handlerName, event, "beforeExecution");
}
for (const user of users) {
try {
await processHandlers(event, user);
}
catch (error) {
logger_manager_1.Log.error(`Error processing event "${event.eventType}" with ID: ${event.id} for user ${user.id}: ${error}`);
}
}
for (const handler of eventHandlerManager.getHandlersForEventType(event.eventType)) {
await processExecutionLifecycle(handler, event, "afterExecution");
}
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