fix: 修复在相同的cron时偶尔无法触发定时任务的bug

This commit is contained in:
xiaojunnuo
2024-08-03 23:32:50 +08:00
parent 1cf8d4e5e7
commit 680941af11
8 changed files with 101 additions and 34 deletions
@@ -35,7 +35,11 @@ export class AutoInitSite {
// 授权许可
const licenseInfo: SysLicenseInfo = await this.sysSettingsService.getSetting(SysLicenseInfo);
await verify(licenseInfo.license);
const req = {
subjectId: installInfo.siteId,
license: licenseInfo.license,
};
await verify(req);
logger.info('初始化站点完成');
}
@@ -120,7 +120,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
}
}
}
logger.info('定时器数量:', this.cron.getListSize());
logger.info('定时器数量:', this.cron.getTaskSize());
}
async registerTriggers(pipeline?: Pipeline, immediateTriggerOnce = false) {
@@ -193,7 +193,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
}
},
});
logger.info('当前定时器数量:', this.cron.getListSize());
logger.info('当前定时器数量:', this.cron.getTaskSize());
}
async run(id: number, triggerId: string) {
@@ -212,6 +212,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
const onChanged = async (history: RunHistory) => {
//保存执行历史
try {
logger.info('保存执行历史:', history.id);
await this.saveHistory(history);
} catch (e) {
const pipelineEntity = new PipelineEntity();
@@ -1,5 +1,7 @@
import cron from 'node-cron';
export type CronTask = {
import parser from 'cron-parser';
import { ILogger } from '@certd/pipeline';
export type CronTaskReq = {
/**
* 为空则为单次执行
*/
@@ -7,39 +9,90 @@ export type CronTask = {
job: () => Promise<void>;
name: string;
};
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);
}
}
export class Cron {
logger;
logger: ILogger;
immediateTriggerOnce: boolean;
constructor(opts) {
bucket: Record<string, CronTask> = {};
constructor(opts: any) {
this.logger = opts.logger;
this.immediateTriggerOnce = opts.immediateTriggerOnce;
}
register(task: CronTask) {
if (!task.cron) {
this.logger.info(`[cron] register once : [${task.name}]`);
task.job();
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 : [${task.name}] ,${task.cron}`);
cron.schedule(task.cron, task.job, {
name: task.name,
});
this.logger.info('当前定时任务数量:', this.getListSize());
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());
}
remove(taskName: string) {
this.logger.info(`[cron] remove : [${taskName}]`);
const tasks = cron.getTasks() as Map<any, any>;
const node = tasks.get(taskName);
if (node) {
node.stop();
tasks.delete(taskName);
const task = this.bucket[taskName];
if (task) {
task.stop();
delete this.bucket[taskName];
}
}
getListSize() {
const tasks = cron.getTasks();
return tasks.size;
getTaskSize() {
const tasks = Object.keys(this.bucket);
return tasks.length;
}
}
@@ -32,5 +32,5 @@ export class SysLicenseInfo extends BaseSettings {
static __title__ = '授权许可信息';
static __key__ = 'sys.license';
static __access__ = 'private';
license: string;
license?: string;
}