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

pull/148/head
xiaojunnuo 2024-08-03 23:32:50 +08:00
parent 1cf8d4e5e7
commit 680941af11
8 changed files with 101 additions and 34 deletions

View File

@ -3,9 +3,8 @@ import { logger } from "../utils/index.js";
const SecreteKey =
"LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJDZ0tDQVFFQXY3TGtMaUp1dGM0NzhTU3RaTExjajVGZXh1YjJwR2NLMGxwa0hwVnlZWjhMY29rRFhuUlAKUGQ5UlJSTVRTaGJsbFl2Mzd4QUhOV1ZIQ0ZsWHkrQklVU001bUlBU1NDQTV0azlJNmpZZ2F4bEFDQm1BY0lGMwozKzBjeGZIYVkrVW9YdVluMkZ6YUt2Ym5GdFZIZ0lkMDg4a3d4clZTZzlCT3BDRVZIR1pxR2I5TWN5MXVHVXhUClFTVENCbmpoTWZlZ0p6cXVPYWVOY0ZPSE5tbmtWRWpLTythbTBPeEhNS1lyS3ZnQnVEbzdoVnFENlBFMUd6V3AKZHdwZUV4QXZDSVJxL2pWTkdRK3FtMkRWOVNJZ3U5bmF4MktmSUtFeU50dUFFS1VpekdqL0VmRFhDM1cxMExhegpKaGNYNGw1SUFZU1o3L3JWVmpGbExWSVl0WDU1T054L1Z3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K";
const appKey = "z4nXOeTeSnnpUpnmsV";
export type LicenseVerifyReq = {
appKey: string;
subjectId: string;
license: string;
};
@ -33,13 +32,10 @@ class LicenseVerifier {
licenseReq?: LicenseVerifyReq = undefined;
async reVerify(req: LicenseVerifyReq) {
this.checked = false;
//@ts-ignore
// globalThis._certd_license_.isPlus = false;
return await this.verify(req);
}
setPlus(value: boolean) {
//@ts-ignore
holder.isPlus = value;
return value;
}
@ -60,7 +56,7 @@ class LicenseVerifier {
logger.warn("授权已过期");
return this.setPlus(false);
}
const content = `${this.licenseReq.appKey},${this.licenseReq.subjectId},${json.code},${json.secret},${json.activeTime},${json.duration},${json.expireTime},${json.version}`;
const content = `${appKey},${this.licenseReq.subjectId},${json.code},${json.secret},${json.activeTime},${json.duration},${json.expireTime},${json.version}`;
const publicKey = Buffer.from(SecreteKey, "base64").toString();
const res = this.verifySignature(content, json.signature, publicKey);
this.checked = true;

View File

@ -336,6 +336,21 @@ function install(app: App, options: any = {}) {
return columnProps;
}
});
registerMergeColumnPlugin({
name: "resize-column-plugin",
order: 2,
handle: (columnProps: ColumnCompositionProps) => {
if (!columnProps.column) {
columnProps.column = {};
}
columnProps.column.resizable = true;
if (!columnProps.column.width) {
columnProps.column.width = 100;
}
return columnProps;
}
});
}
export default {

View File

@ -6,12 +6,10 @@ export function useReference(form: any) {
return;
}
for (const reference of form.reference) {
debugger;
_.set(
form,
reference.dest,
compute<any>((scope) => {
debugger;
return _.get(scope, reference.src);
})
);

View File

@ -42,6 +42,7 @@
"bcryptjs": "^2.4.3",
"better-sqlite3": "^11.1.2",
"cache-manager": "^3.6.3",
"cron-parser": "^4.9.0",
"dayjs": "^1.11.7",
"glob": "^10.4.5",
"https-proxy-agent": "^7.0.4",
@ -56,7 +57,6 @@
"md5": "^2.3.0",
"mwtsc": "^1.4.0",
"nanoid": "^4.0.0",
"node-cron": "^3.0.2",
"nodemailer": "^6.9.3",
"pg": "^8.12.0",
"reflect-metadata": "^0.1.13",

View File

@ -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('初始化站点完成');
}

View File

@ -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();

View File

@ -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;
}
}

View File

@ -32,5 +32,5 @@ export class SysLicenseInfo extends BaseSettings {
static __title__ = '授权许可信息';
static __key__ = 'sys.license';
static __access__ = 'private';
license: string;
license?: string;
}