UNPKG

@forzalabs/remora

Version:

A powerful CLI tool for seamless data translation.

223 lines (222 loc) 9.1 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 __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const cron = __importStar(require("node-cron")); const Environment_1 = __importDefault(require("../Environment")); const ExecutorOrchestrator_1 = __importDefault(require("../../executors/ExecutorOrchestrator")); const settings_1 = require("../../settings"); class CronScheduler { constructor() { this.scheduledJobs = new Map(); this.isInitialized = false; } /** * Initialize the CRON scheduler by scanning all consumers and scheduling those with CRON triggers */ initialize() { if (this.isInitialized) { console.log('CRON scheduler already initialized'); return; } console.log('Initializing CRON scheduler...'); try { const consumers = Environment_1.default.getAllConsumers(); let cronJobCount = 0; for (const consumer of consumers) { if (this.hasCronTrigger(consumer)) { this.scheduleConsumer(consumer); cronJobCount++; } } this.isInitialized = true; console.log(`CRON scheduler initialized with ${cronJobCount} scheduled jobs`); } catch (error) { console.error('Failed to initialize CRON scheduler:', error); throw error; } } /** * Check if a consumer has any CRON triggers configured */ hasCronTrigger(consumer) { return consumer.outputs.some(output => { var _a; return ((_a = output.trigger) === null || _a === void 0 ? void 0 : _a.type) === 'CRON' && output.trigger.value; }); } /** * Schedule a consumer with CRON triggers */ scheduleConsumer(consumer) { consumer.outputs.forEach((output, index) => { var _a; if (((_a = output.trigger) === null || _a === void 0 ? void 0 : _a.type) === 'CRON' && output.trigger.value) { const jobKey = `${consumer.name}_output_${index}`; const cronExpression = output.trigger.value; try { // Validate CRON expression if (!cron.validate(cronExpression)) { console.error(`Invalid CRON expression for consumer ${consumer.name}: ${cronExpression}`); return; } // Schedule the job const task = cron.schedule(cronExpression, () => __awaiter(this, void 0, void 0, function* () { yield this.executeConsumerOutput(consumer, output, index); })); // Don't start the task immediately, we'll start it manually task.stop(); this.scheduledJobs.set(jobKey, task); task.start(); console.log(`Scheduled CRON job for consumer "${consumer.name}" output ${index} with expression: ${cronExpression}`); } catch (error) { console.error(`Failed to schedule CRON job for consumer ${consumer.name}:`, error); } } }); } /** * Execute a consumer output when triggered by CRON */ executeConsumerOutput(consumer, output, outputIndex) { return __awaiter(this, void 0, void 0, function* () { try { console.log(`Executing CRON job for consumer "${consumer.name}" output ${outputIndex}`); const user = settings_1.REMORA_WORKER_USER; const runner = { _id: user._id, name: user.name, type: 'actor' }; const result = yield ExecutorOrchestrator_1.default.launch({ consumer, details: { invokedBy: 'CRON', user: runner }, logProgress: false }); console.log(`CRON job completed successfully for consumer "${consumer.name}" output ${outputIndex}`); // Log execution statistics if (result) { console.log(`CRON job stats: ${result.elapsedMS}ms, size: ${result.outputCount}, cycles: ${result.cycles}`); } } catch (error) { console.error(`CRON job failed for consumer "${consumer.name}" output ${outputIndex}:`, error); // Optionally, you could implement error handling strategies here: // - Send notifications // - Log to a monitoring system // - Retry logic // - Disable the job after repeated failures } }); } /** * Add or update a CRON job for a specific consumer */ updateConsumerSchedule(consumer) { // First, remove any existing schedules for this consumer this.removeConsumerSchedule(consumer.name); // Then, add new schedules if they have CRON triggers if (this.hasCronTrigger(consumer)) { this.scheduleConsumer(consumer); } } /** * Remove all scheduled jobs for a consumer */ removeConsumerSchedule(consumerName) { const jobsToRemove = Array.from(this.scheduledJobs.keys()).filter(key => key.startsWith(`${consumerName}_output_`)); jobsToRemove.forEach(jobKey => { const task = this.scheduledJobs.get(jobKey); if (task) { task.stop(); task.destroy(); this.scheduledJobs.delete(jobKey); console.log(`Removed CRON job: ${jobKey}`); } }); } /** * Get information about all scheduled jobs */ getScheduledJobs() { return Array.from(this.scheduledJobs.entries()).map(([jobKey, task]) => ({ jobKey, isRunning: task.getStatus() === 'scheduled' })); } /** * Stop all scheduled jobs */ stopAllJobs() { console.log('Stopping all CRON jobs...'); this.scheduledJobs.forEach((task, jobKey) => { task.stop(); task.destroy(); console.log(`Stopped CRON job: ${jobKey}`); }); this.scheduledJobs.clear(); this.isInitialized = false; console.log('All CRON jobs stopped'); } /** * Restart the scheduler (useful for configuration reloads) */ restart() { console.log('Restarting CRON scheduler...'); this.stopAllJobs(); this.initialize(); } /** * Get the scheduler status */ getStatus() { return { initialized: this.isInitialized, jobCount: this.scheduledJobs.size, jobs: this.getScheduledJobs() }; } } // Export a singleton instance exports.default = new CronScheduler();