// node_api/services/jobManager.js const { jobScheduler } = require('../jobs/scheduler'); const { testConnection, initializeModels } = require('../config/database'); const { logger } = require('../utils/logger'); class JobManager { constructor() { this.isInitialized = false; this.isRunning = false; } /** * Initialize job manager and all dependencies */ async initialize() { if (this.isInitialized) { logger.warn('Job manager already initialized'); return; } try { // Test database connection const dbConnected = await testConnection(); if (!dbConnected) { throw new Error('Database connection failed'); } // Initialize database models const modelsInitialized = await initializeModels(); if (!modelsInitialized) { throw new Error('Database models initialization failed'); } // Initialize job scheduler await jobScheduler.initialize(); this.isInitialized = true; logger.info('Job manager initialized successfully'); } catch (error) { logger.error('Failed to initialize job manager:', error); throw error; } } /** * Start all scheduled jobs */ async start() { if (!this.isInitialized) { throw new Error('Job manager not initialized'); } if (this.isRunning) { logger.warn('Job manager already running'); return; } try { jobScheduler.startAll(); this.isRunning = true; logger.info('Job manager started - all jobs scheduled'); } catch (error) { logger.error('Failed to start job manager:', error); throw error; } } /** * Stop all scheduled jobs */ async stop() { if (!this.isRunning) { logger.warn('Job manager not running'); return; } try { jobScheduler.stopAll(); this.isRunning = false; logger.info('Job manager stopped'); } catch (error) { logger.error('Failed to stop job manager:', error); throw error; } } /** * Get status of all jobs */ getJobStatuses() { if (!this.isInitialized) { throw new Error('Job manager not initialized'); } return { managerStatus: { initialized: this.isInitialized, running: this.isRunning }, jobs: jobScheduler.getAllJobStatuses() }; } /** * Run a job manually */ async runJobManually(jobName) { if (!this.isInitialized) { throw new Error('Job manager not initialized'); } try { logger.info(`Running job manually: ${jobName}`); const result = await jobScheduler.runManual(jobName); return result; } catch (error) { logger.error(`Failed to run job manually: ${jobName}`, error); throw error; } } /** * Get job execution history */ async getJobHistory(jobName, limit = 50) { if (!this.isInitialized) { throw new Error('Job manager not initialized'); } try { return await jobScheduler.getJobHistory(jobName, limit); } catch (error) { logger.error(`Failed to get job history for: ${jobName}`, error); throw error; } } /** * Health check for job manager */ async healthCheck() { const health = { status: 'healthy', timestamp: new Date().toISOString(), details: { initialized: this.isInitialized, running: this.isRunning, database: false, jobs: {} } }; try { // Check database connection health.details.database = await testConnection(); // Check job statuses if (this.isInitialized) { health.details.jobs = jobScheduler.getAllJobStatuses(); } // Determine overall health if (!health.details.database || !this.isInitialized) { health.status = 'unhealthy'; } else if (!this.isRunning) { health.status = 'degraded'; } } catch (error) { health.status = 'unhealthy'; health.error = error.message; logger.error('Job manager health check failed:', error); } return health; } /** * Graceful shutdown */ async shutdown() { logger.info('Shutting down job manager...'); try { if (this.isRunning) { await this.stop(); } if (this.isInitialized) { jobScheduler.destroy(); } logger.info('Job manager shutdown complete'); } catch (error) { logger.error('Error during job manager shutdown:', error); throw error; } } } // Export singleton instance const jobManager = new JobManager(); module.exports = { jobManager, JobManager };