Compare commits

..

5 Commits

Author SHA1 Message Date
xiaojunnuo
fbf4959463 v1.22.9 2024-08-05 16:10:39 +08:00
xiaojunnuo
02bb0be06a chore: 2024-08-05 16:07:28 +08:00
xiaojunnuo
87e440ee2a perf: 优化定时任务 2024-08-05 16:00:04 +08:00
xiaojunnuo
2182dce07c chore: 修复pipelineid为空被注册任务 2024-08-05 15:08:24 +08:00
xiaojunnuo
3f0a10007c build: trigger build image 2024-08-05 13:20:09 +08:00
13 changed files with 115 additions and 39 deletions

View File

@@ -3,6 +3,12 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.22.9](https://github.com/certd/certd/compare/v1.22.8...v1.22.9) (2024-08-05)
### Performance Improvements
* 优化定时任务 ([87e440e](https://github.com/certd/certd/commit/87e440ee2a8b10dc571ce619f28bc83c1e5eb147))
## [1.22.8](https://github.com/certd/certd/compare/v1.22.7...v1.22.8) (2024-08-05)
### Performance Improvements

View File

@@ -1 +1 @@
22:33
13:20

View File

@@ -9,5 +9,5 @@
}
},
"npmClient": "pnpm",
"version": "1.22.8"
"version": "1.22.9"
}

View File

@@ -3,6 +3,12 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.22.9](https://github.com/certd/certd/compare/v1.22.8...v1.22.9) (2024-08-05)
### Performance Improvements
* 优化定时任务 ([87e440e](https://github.com/certd/certd/commit/87e440ee2a8b10dc571ce619f28bc83c1e5eb147))
## [1.22.8](https://github.com/certd/certd/compare/v1.22.7...v1.22.8) (2024-08-05)
### Performance Improvements

View File

@@ -1,6 +1,6 @@
{
"name": "@certd/ui-client",
"version": "1.22.8",
"version": "1.22.9",
"private": true,
"scripts": {
"dev": "vite --open",

View File

@@ -187,6 +187,9 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp
title: "ID",
key: "id",
type: "number",
search: {
show: true
},
column: {
width: 50
},
@@ -233,6 +236,31 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp
}
}
},
content: {
title: "定时任务数量",
type: "number",
column: {
cellRender({ value }) {
if (value && value.triggers) {
return value.triggers?.length > 0 ? value.triggers.length : "-";
}
return "-";
}
},
valueBuilder({ row }) {
if (row.content) {
row.content = JSON.parse(row.content);
}
},
valueResolve({ row }) {
if (row.content) {
row.content = JSON.stringify(row.content);
}
},
form: {
show: false
}
},
lastVars: {
title: "到期剩余",
type: "number",

View File

@@ -3,6 +3,12 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.22.9](https://github.com/certd/certd/compare/v1.22.8...v1.22.9) (2024-08-05)
### Performance Improvements
* 优化定时任务 ([87e440e](https://github.com/certd/certd/commit/87e440ee2a8b10dc571ce619f28bc83c1e5eb147))
## [1.22.8](https://github.com/certd/certd/compare/v1.22.7...v1.22.8) (2024-08-05)
### Performance Improvements

View File

@@ -1,6 +1,6 @@
{
"name": "@certd/ui-server",
"version": "1.22.8",
"version": "1.22.9",
"description": "fast-server base midway",
"private": true,
"type": "module",

View File

@@ -73,6 +73,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
const info = await this.info(pipelineId);
if (info && !info.disabled) {
const pipeline = JSON.parse(info.content);
// 手动触发不要await
this.registerTriggers(pipeline);
}
}
@@ -87,15 +88,16 @@ export class PipelineService extends BaseService<PipelineEntity> {
}
async update(bean: PipelineEntity) {
await this.clearTriggers(bean.id);
//更新非trigger部分
await super.update(bean);
await this.registerTriggerById(bean.id);
}
async save(bean: PipelineEntity) {
await this.clearTriggers(bean.id);
const pipeline = JSON.parse(bean.content);
bean.title = pipeline.title;
if (bean.content) {
const pipeline = JSON.parse(bean.content);
bean.title = pipeline.title;
}
await this.addOrUpdate(bean);
await this.registerTriggerById(bean.id);
}
@@ -173,7 +175,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
if (immediateTriggerOnce) {
await this.trigger(pipeline.id);
await sleep(1000);
await sleep(200);
}
}
@@ -224,6 +226,11 @@ export class PipelineService extends BaseService<PipelineEntity> {
}
registerCron(pipelineId, trigger) {
if (pipelineId == null) {
logger.warn('pipelineId为空无法注册定时任务');
return;
}
let cron = trigger.props?.cron;
if (cron == null) {
return;
@@ -232,15 +239,20 @@ export class PipelineService extends BaseService<PipelineEntity> {
if (cron.startsWith('*')) {
cron = '0' + cron.substring(1, cron.length);
}
const name = this.buildCronKey(pipelineId, trigger.id);
const triggerId = trigger.id;
const name = this.buildCronKey(pipelineId, triggerId);
this.cron.remove(name);
this.cron.register({
name,
cron,
job: async () => {
logger.info('定时任务触发:', pipelineId, trigger.id);
logger.info('定时任务触发:', pipelineId, triggerId);
if (pipelineId == null) {
logger.warn('pipelineId为空,无法执行');
return;
}
try {
await this.run(pipelineId, trigger.id);
await this.run(pipelineId, triggerId);
} catch (e) {
logger.error('定时job执行失败', e);
}

View File

@@ -22,6 +22,7 @@ export class CronConfiguration {
...this.config,
});
container.registerObject('cron', this.cron);
this.cron.start();
this.logger.info('cron started');
}
}

View File

@@ -17,56 +17,63 @@ export class CronTask {
name: string;
stoped = false;
timeoutId: any;
nextTime: any;
constructor(req: CronTaskReq, logger: ILogger) {
this.cron = req.cron;
this.job = req.job;
this.name = req.name;
this.logger = logger;
this.start();
this.genNextTime();
}
start() {
genNextTime() {
if (!this.cron) {
return;
return null;
}
if (this.stoped) {
return;
return null;
}
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);
this.logger.info(`[cron] [${this.name}], cron:${this.cron}, next run :${new Date(next).toLocaleString()}`);
this.nextTime = next;
return next;
}
stop() {
this.stoped = true;
clearTimeout(this.timeoutId);
}
}
export class Cron {
logger: ILogger;
immediateTriggerOnce: boolean;
bucket: Record<string, CronTask> = {};
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}]`);
@@ -78,21 +85,22 @@ export class Cron {
this.logger.info(`[cron] register cron : [${req.name}] ,${req.cron}`);
const task = new CronTask(req, this.logger);
this.bucket[task.name] = task;
this.queue.push(task);
this.logger.info('当前定时任务数量:', this.getTaskSize());
}
remove(taskName: string) {
this.logger.info(`[cron] remove : [${taskName}]`);
const task = this.bucket[taskName];
if (task) {
task.stop();
delete this.bucket[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.bucket);
const tasks = Object.keys(this.queue);
return tasks.length;
}
}

View File

@@ -75,6 +75,10 @@ export class AsyncSsh2Client {
}
async exec(script: string) {
if (!script) {
this.logger.info('script 为空,取消执行');
return;
}
return new Promise((resolve, reject) => {
this.logger.info(`执行命令:[${this.connConf.host}][exec]: ` + script);
this.conn.exec(script, (err: Error, stream: any) => {
@@ -97,6 +101,10 @@ export class AsyncSsh2Client {
data += out;
this.logger.info(`[${this.connConf.host}][info]: ` + out.trimEnd());
})
.on('error', (err: any) => {
reject(err);
this.logger.error(err);
})
.stderr.on('data', (ret: Buffer) => {
const err = this.convert(ret);
data += err;

View File

@@ -30,6 +30,7 @@ export class HostShellExecutePlugin extends AbstractTaskPlugin {
name: 'a-textarea',
vModel: 'value',
},
required: true,
})
script!: string;