2024-08-03 23:32:50 +08:00
|
|
|
import parser from 'cron-parser';
|
|
|
|
|
import { ILogger } from '@certd/pipeline';
|
|
|
|
|
|
|
|
|
|
export type CronTaskReq = {
|
2023-01-29 13:44:19 +08:00
|
|
|
/**
|
|
|
|
|
* 为空则为单次执行
|
|
|
|
|
*/
|
|
|
|
|
cron: string;
|
|
|
|
|
job: () => Promise<void>;
|
|
|
|
|
name: string;
|
|
|
|
|
};
|
2024-08-03 23:32:50 +08:00
|
|
|
|
|
|
|
|
export class CronTask {
|
|
|
|
|
logger: ILogger;
|
|
|
|
|
cron: string;
|
|
|
|
|
job: () => Promise<void>;
|
|
|
|
|
name: string;
|
|
|
|
|
stoped = false;
|
|
|
|
|
|
|
|
|
|
timeoutId: any;
|
|
|
|
|
|
|
|
|
|
constructor(req: CronTaskReq, logger: ILogger) {
|
|
|
|
|
this.cron = req.cron;
|
|
|
|
|
this.job = req.job;
|
|
|
|
|
this.name = req.name;
|
|
|
|
|
this.logger = logger;
|
|
|
|
|
this.start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
start() {
|
|
|
|
|
if (!this.cron) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (this.stoped) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const interval = parser.parseExpression(this.cron);
|
|
|
|
|
const next = interval.next().getTime();
|
|
|
|
|
const now = Date.now();
|
|
|
|
|
const delay = next - now;
|
|
|
|
|
this.timeoutId = setTimeout(async () => {
|
|
|
|
|
try {
|
|
|
|
|
if (this.stoped) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
await this.job();
|
|
|
|
|
} catch (e) {
|
|
|
|
|
this.logger.error(`[cron] job error : [${this.name}]`, e);
|
|
|
|
|
}
|
|
|
|
|
this.start();
|
|
|
|
|
}, delay);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stop() {
|
|
|
|
|
this.stoped = true;
|
|
|
|
|
clearTimeout(this.timeoutId);
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-01-29 13:44:19 +08:00
|
|
|
export class Cron {
|
2024-08-03 23:32:50 +08:00
|
|
|
logger: ILogger;
|
2024-07-21 02:32:03 +08:00
|
|
|
immediateTriggerOnce: boolean;
|
2024-08-03 23:32:50 +08:00
|
|
|
|
|
|
|
|
bucket: Record<string, CronTask> = {};
|
|
|
|
|
|
|
|
|
|
constructor(opts: any) {
|
2023-01-29 13:44:19 +08:00
|
|
|
this.logger = opts.logger;
|
2024-07-21 02:32:03 +08:00
|
|
|
this.immediateTriggerOnce = opts.immediateTriggerOnce;
|
2023-01-29 13:44:19 +08:00
|
|
|
}
|
|
|
|
|
|
2024-08-03 23:32:50 +08:00
|
|
|
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);
|
|
|
|
|
});
|
2023-01-29 13:44:19 +08:00
|
|
|
return;
|
|
|
|
|
}
|
2024-08-03 23:32:50 +08:00
|
|
|
this.logger.info(`[cron] register cron : [${req.name}] ,${req.cron}`);
|
|
|
|
|
|
|
|
|
|
const task = new CronTask(req, this.logger);
|
|
|
|
|
this.bucket[task.name] = task;
|
|
|
|
|
this.logger.info('当前定时任务数量:', this.getTaskSize());
|
2023-01-29 13:44:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
remove(taskName: string) {
|
|
|
|
|
this.logger.info(`[cron] remove : [${taskName}]`);
|
2024-08-03 23:32:50 +08:00
|
|
|
const task = this.bucket[taskName];
|
|
|
|
|
if (task) {
|
|
|
|
|
task.stop();
|
|
|
|
|
delete this.bucket[taskName];
|
2023-05-24 15:41:35 +08:00
|
|
|
}
|
2023-01-29 13:44:19 +08:00
|
|
|
}
|
|
|
|
|
|
2024-08-03 23:32:50 +08:00
|
|
|
getTaskSize() {
|
|
|
|
|
const tasks = Object.keys(this.bucket);
|
|
|
|
|
return tasks.length;
|
2023-01-29 13:44:19 +08:00
|
|
|
}
|
|
|
|
|
}
|