204 lines
4.6 KiB
JavaScript
204 lines
4.6 KiB
JavaScript
// 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 }; |