tududi/backend/services/taskScheduler.js
Chris 3c1209a5a9
Express migration (#80)
* Initial migration

* Cleanup and create migration scripts

* Introduce test suite

* Fix test issues

* Correct CORS issue and update paths

* Update README
2025-06-16 21:50:44 +03:00

181 lines
No EOL
5.2 KiB
JavaScript

const cron = require('node-cron');
const { User } = require('../models');
const TaskSummaryService = require('./taskSummaryService');
class TaskScheduler {
constructor() {
this.jobs = new Map();
this.isInitialized = false;
}
static getInstance() {
if (!TaskScheduler.instance) {
TaskScheduler.instance = new TaskScheduler();
}
return TaskScheduler.instance;
}
async initialize() {
if (this.isInitialized) {
console.log('Task scheduler already initialized');
return;
}
// Don't schedule in test environment
if (process.env.NODE_ENV === 'test' || process.env.DISABLE_SCHEDULER === 'true') {
console.log('Task scheduler disabled for test environment');
return;
}
console.log('Initializing task scheduler...');
// Daily schedule at 7 AM (for users with daily frequency)
const dailyJob = cron.schedule('0 7 * * *', async () => {
console.log('Running scheduled task: Daily task summary');
await this.processSummariesForFrequency('daily');
}, {
scheduled: false,
timezone: 'UTC'
});
// Weekdays schedule at 7 AM (Monday through Friday)
const weekdaysJob = cron.schedule('0 7 * * 1-5', async () => {
console.log('Running scheduled task: Weekday task summary');
await this.processSummariesForFrequency('weekdays');
}, {
scheduled: false,
timezone: 'UTC'
});
// Weekly schedule at 7 AM on Monday
const weeklyJob = cron.schedule('0 7 * * 1', async () => {
console.log('Running scheduled task: Weekly task summary');
await this.processSummariesForFrequency('weekly');
}, {
scheduled: false,
timezone: 'UTC'
});
// Hourly schedules
const hourlyJob = cron.schedule('0 * * * *', async () => {
console.log('Running scheduled task: Hourly (1h) task summary');
await this.processSummariesForFrequency('1h');
}, {
scheduled: false,
timezone: 'UTC'
});
const twoHourlyJob = cron.schedule('0 */2 * * *', async () => {
console.log('Running scheduled task: 2-hour task summary');
await this.processSummariesForFrequency('2h');
}, {
scheduled: false,
timezone: 'UTC'
});
const fourHourlyJob = cron.schedule('0 */4 * * *', async () => {
console.log('Running scheduled task: 4-hour task summary');
await this.processSummariesForFrequency('4h');
}, {
scheduled: false,
timezone: 'UTC'
});
const eightHourlyJob = cron.schedule('0 */8 * * *', async () => {
console.log('Running scheduled task: 8-hour task summary');
await this.processSummariesForFrequency('8h');
}, {
scheduled: false,
timezone: 'UTC'
});
const twelveHourlyJob = cron.schedule('0 */12 * * *', async () => {
console.log('Running scheduled task: 12-hour task summary');
await this.processSummariesForFrequency('12h');
}, {
scheduled: false,
timezone: 'UTC'
});
// Store jobs for later management
this.jobs.set('daily', dailyJob);
this.jobs.set('weekdays', weekdaysJob);
this.jobs.set('weekly', weeklyJob);
this.jobs.set('1h', hourlyJob);
this.jobs.set('2h', twoHourlyJob);
this.jobs.set('4h', fourHourlyJob);
this.jobs.set('8h', eightHourlyJob);
this.jobs.set('12h', twelveHourlyJob);
// Start all jobs
this.jobs.forEach((job, frequency) => {
job.start();
console.log(`Started scheduler for frequency: ${frequency}`);
});
this.isInitialized = true;
console.log('Task scheduler initialized successfully');
}
async processSummariesForFrequency(frequency) {
try {
const users = await User.findAll({
where: {
telegram_bot_token: { [require('sequelize').Op.ne]: null },
telegram_chat_id: { [require('sequelize').Op.ne]: null },
task_summary_enabled: true,
task_summary_frequency: frequency
}
});
console.log(`Processing ${users.length} users for frequency: ${frequency}`);
for (const user of users) {
try {
const success = await TaskSummaryService.sendSummaryToUser(user.id);
if (success) {
console.log(`Sent ${frequency} summary to user ${user.id}`);
} else {
console.log(`Failed to send ${frequency} summary to user ${user.id}`);
}
} catch (error) {
console.error(`Error sending ${frequency} summary to user ${user.id}:`, error.message);
}
}
} catch (error) {
console.error(`Error processing summaries for frequency ${frequency}:`, error);
}
}
async stop() {
if (!this.isInitialized) {
console.log('Task scheduler not initialized, nothing to stop');
return;
}
console.log('Stopping task scheduler...');
this.jobs.forEach((job, frequency) => {
job.stop();
console.log(`Stopped scheduler for frequency: ${frequency}`);
});
this.jobs.clear();
this.isInitialized = false;
console.log('Task scheduler stopped');
}
async restart() {
await this.stop();
await this.initialize();
}
getStatus() {
return {
initialized: this.isInitialized,
jobCount: this.jobs.size,
jobs: Array.from(this.jobs.keys())
};
}
}
module.exports = TaskScheduler;