Files
certd/packages/ui/certd-server/src/modules/cron/cron.ts
2024-11-04 16:39:02 +08:00

108 lines
2.5 KiB
TypeScript

import parser from 'cron-parser';
import { ILogger } from '@certd/basic';
export type CronTaskReq = {
/**
* 为空则为单次执行
*/
cron: string;
job: () => Promise<void>;
name: string;
};
export class CronTask {
logger: ILogger;
cron: string;
job: () => Promise<void>;
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;
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}`);
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;
}
}