import parser from 'cron-parser'; import { ILogger, logger } from '@certd/basic'; export type CronTaskReq = { /** * 为空则为单次执行 */ cron: string; job: () => Promise; name: string; }; export class CronTask { logger: ILogger; cron: string; job: () => Promise; name: string; stoped = false; nextTime: any; constructor(req: CronTaskReq, logger: ILogger) { this.cron = req.cron; this.job = req.job; this.name = req.name; this.logger = logger; this.logger.info(`[cron] CronTask created [${this.name}], cron:${this.cron}`); this.genNextTime(); } genNextTime() { if (!this.cron) { return null; } if (this.stoped) { return null; } const interval = parser.parseExpression(this.cron); const next = interval.next().getTime(); this.logger.info(`[cron] [${this.name}], cron:${this.cron}, next run :${new Date(next).toLocaleString()}`); this.nextTime = next; return next; } stop() { this.stoped = true; } } export class Cron { logger: ILogger; immediateTriggerOnce: boolean; queue: CronTask[] = []; constructor(opts: any) { this.logger = opts.logger || logger; this.immediateTriggerOnce = opts.immediateTriggerOnce; } start() { this.logger.info('[cron] start'); this.queue.forEach(task => { task.genNextTime(); }); setInterval(() => { const now = new Date().getTime(); for (const task of this.queue) { if (task.nextTime <= now) { task.job().catch(e => { this.logger.error(`job execute error : [${task.name}]`, e); }); task.genNextTime(); } } }, 1000 * 60); } register(req: CronTaskReq) { if (!req.cron) { this.logger.info(`[cron] register once : [${req.name}]`); req.job().catch(e => { this.logger.error(`job execute error : [${req.name}]`, e); }); return; } this.logger.info(`[cron] register cron : [${req.name}] ,${req.cron}`); this.remove(req.name) const task = new CronTask(req, this.logger); this.queue.push(task); this.logger.info('当前定时任务数量:', this.getTaskSize()); } remove(taskName: string) { this.logger.info(`[cron] remove : [${taskName}]`); const index = this.queue.findIndex(item => item.name === taskName); if (index !== -1) { this.queue[index].stop(); this.queue.splice(index, 1); } this.logger.info('当前定时任务数量:', this.getTaskSize()); } getTaskSize() { const tasks = Object.keys(this.queue); return tasks.length; } }