javascript
Utilities
Cron Job Manager
Node.js cron job manager with job registration, error handling, execution logging, and graceful shutdown.
Apex Logic
0 copies
javascript
const cron = require('node-cron');
class CronManager {
constructor() {
this.jobs = new Map();
this.logs = [];
}
register(name, schedule, handler, options = {}) {
if (this.jobs.has(name)) {
console.warn(`Cron job '${name}' already registered. Skipping.`);
return this;
}
const { timezone, runOnInit = false, enabled = true } = options;
if (!cron.validate(schedule)) {
throw new Error(`Invalid cron schedule for '${name}': ${schedule}`);
}
const wrappedHandler = async () => {
const start = Date.now();
const logEntry = { name, startedAt: new Date(), status: 'running' };
try {
console.log(`[CRON] Running: ${name}`);
await handler();
logEntry.status = 'success';
logEntry.duration = Date.now() - start;
console.log(`[CRON] Completed: ${name} (${logEntry.duration}ms)`);
} catch (err) {
logEntry.status = 'failed';
logEntry.error = err.message;
logEntry.duration = Date.now() - start;
console.error(`[CRON] Failed: ${name} -`, err.message);
}
this.logs.push(logEntry);
if (this.logs.length > 1000) this.logs.shift();
};
const task = cron.schedule(schedule, wrappedHandler, {
scheduled: enabled,
timezone,
});
this.jobs.set(name, { task, schedule, handler: wrappedHandler, options });
if (runOnInit) wrappedHandler();
console.log(`[CRON] Registered: ${name} (${schedule})`);
return this;
}
start(name) {
const job = this.jobs.get(name);
if (job) job.task.start();
return this;
}
stop(name) {
const job = this.jobs.get(name);
if (job) job.task.stop();
return this;
}
stopAll() {
for (const [name, { task }] of this.jobs) {
task.stop();
console.log(`[CRON] Stopped: ${name}`);
}
}
getStatus() {
const status = {};
for (const [name, { schedule }] of this.jobs) {
const lastLog = [...this.logs].reverse().find(l => l.name === name);
status[name] = { schedule, lastRun: lastLog || null };
}
return status;
}
getLogs(name, limit = 50) {
const filtered = name ? this.logs.filter(l => l.name === name) : this.logs;
return filtered.slice(-limit);
}
}
module.exports = new CronManager();