From 59897c4ceae992ebe2972ca9e8f9196616ffdfd7 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Sun, 4 Aug 2024 02:35:45 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E6=B5=81=E6=B0=B4=E7=BA=BF=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=90=8D=E7=A7=B0=E6=A8=A1=E7=B3=8A=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/pipeline/src/core/executor.ts | 14 ++++- packages/core/pipeline/src/plugin/api.ts | 9 +-- .../src/plugin/cert-plugin/base.ts | 2 + .../src/plugin/fast-crud/index.tsx | 4 +- .../src/views/certd/pipeline/crud.tsx | 57 +++++++++++++++++++ .../migration-pg/v10006__pipeline_title.sql | 4 ++ .../db/migration/v10006__pipeline_title.sql | 3 + .../ui/certd-server/src/basic/base-service.ts | 5 +- .../certd-server/src/basic/crud-controller.ts | 8 +-- .../controller/pipeline-controller.ts | 13 ++++- .../src/modules/pipeline/entity/pipeline.ts | 10 ++++ .../modules/pipeline/service/db-storage.ts | 2 +- .../pipeline/service/pipeline-service.ts | 42 ++++++++++++-- .../pipeline/service/storage-service.ts | 12 +++- 14 files changed, 157 insertions(+), 28 deletions(-) diff --git a/packages/core/pipeline/src/core/executor.ts b/packages/core/pipeline/src/core/executor.ts index 39f6e847..79b4b7d0 100644 --- a/packages/core/pipeline/src/core/executor.ts +++ b/packages/core/pipeline/src/core/executor.ts @@ -246,18 +246,26 @@ export class Executor { await instance.onInstance(); await instance.execute(); - + //执行结果处理 if (instance._result.clearLastStatus) { + //是否需要清除所有状态 this.lastStatusMap.clear(); } - //输出到output context + //输出上下文变量到output context _.forEach(define.output, (item: any, key: any) => { step.status!.output[key] = instance[key]; const stepOutputKey = `step.${step.id}.${key}`; this.runtime.context[stepOutputKey] = instance[key]; }); - step.status!.files = instance.getFiles(); + + //更新pipeline vars + if (Object.keys(instance._result.pipelineVars).length > 0) { + // 判断 pipelineVars 有值时更新 + const vars = this.pipelineContext.getObj("vars"); + _.merge(vars, instance._result.pipelineVars); + await this.pipelineContext.setObj("vars", vars); + } } async notification(when: NotificationWhen, error?: any) { diff --git a/packages/core/pipeline/src/plugin/api.ts b/packages/core/pipeline/src/plugin/api.ts index 850d1a8c..4f18a968 100644 --- a/packages/core/pipeline/src/plugin/api.ts +++ b/packages/core/pipeline/src/plugin/api.ts @@ -51,6 +51,7 @@ export type ITaskPlugin = { export type TaskResult = { clearLastStatus?: boolean; files?: FileItem[]; + pipelineVars: Record; }; export type TaskInstanceContext = { pipeline: Pipeline; @@ -66,7 +67,7 @@ export type TaskInstanceContext = { }; export abstract class AbstractTaskPlugin implements ITaskPlugin { - _result: TaskResult = { clearLastStatus: false, files: [] }; + _result: TaskResult = { clearLastStatus: false, files: [], pipelineVars: {} }; ctx!: TaskInstanceContext; clearLastStatus() { this._result.clearLastStatus = true; @@ -83,12 +84,6 @@ export abstract class AbstractTaskPlugin implements ITaskPlugin { randomFileId() { return Math.random().toString(36).substring(2, 9); } - linkFile(file: FileItem) { - this._result.files?.push({ - ...file, - id: this.randomFileId(), - }); - } saveFile(filename: string, file: Buffer) { const filePath = this.ctx.fileStore.writeFile(filename, file); logger.info(`saveFile:${filePath}`); diff --git a/packages/plugins/plugin-cert/src/plugin/cert-plugin/base.ts b/packages/plugins/plugin-cert/src/plugin/cert-plugin/base.ts index 3f1b61f3..26a9af40 100644 --- a/packages/plugins/plugin-cert/src/plugin/cert-plugin/base.ts +++ b/packages/plugins/plugin-cert/src/plugin/cert-plugin/base.ts @@ -138,6 +138,8 @@ export abstract class CertApplyBasePlugin extends AbstractTaskPlugin { const cert: CertInfo = certReader.toCertInfo(); this.cert = cert; + this._result.pipelineVars.certExpiresTime = dayjs(certReader.detail.validity.notAfter).unix(); + if (isNew) { const applyTime = dayjs(certReader.detail.validity.notBefore).format("YYYYMMDD_HHmmss"); await this.zipCert(cert, applyTime); diff --git a/packages/ui/certd-client/src/plugin/fast-crud/index.tsx b/packages/ui/certd-client/src/plugin/fast-crud/index.tsx index 089b6591..7b75d504 100644 --- a/packages/ui/certd-client/src/plugin/fast-crud/index.tsx +++ b/packages/ui/certd-client/src/plugin/fast-crud/index.tsx @@ -61,7 +61,7 @@ function install(app: App, options: any = {}) { }, size: "small", pagination: false, - onResizeColumn: (w: number, col: any) => { + onResizeColumn: (w: number | string, col: any) => { if (crudBinding.value?.table?.columnsMap && crudBinding.value?.table?.columnsMap[col.key]) { crudBinding.value.table.columnsMap[col.key].width = w; } @@ -347,6 +347,8 @@ function install(app: App, options: any = {}) { columnProps.column.resizable = true; if (!columnProps.column.width) { columnProps.column.width = 100; + } else if (typeof columnProps.column?.width === "string" && columnProps.column.width.indexOf("px") > -1) { + columnProps.column.width = parseInt(columnProps.column.width.replace("px", "")); } return columnProps; } diff --git a/packages/ui/certd-client/src/views/certd/pipeline/crud.tsx b/packages/ui/certd-client/src/views/certd/pipeline/crud.tsx index dd7eff2a..f9cb7403 100644 --- a/packages/ui/certd-client/src/views/certd/pipeline/crud.tsx +++ b/packages/ui/certd-client/src/views/certd/pipeline/crud.tsx @@ -8,6 +8,7 @@ import { nanoid } from "nanoid"; import { message, Modal } from "ant-design-vue"; import { env } from "/@/utils/util.env"; import { useUserStore } from "/@/store/modules/user"; +import dayjs from "dayjs"; export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOptionsProps): CreateCrudOptionsRet { const router = useRouter(); @@ -125,6 +126,8 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp } }, rowHandle: { + minWidth: 200, + fixed: "right", buttons: { view: { click({ row }) { @@ -200,6 +203,7 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp }, column: { width: 300, + sorter: true, component: { on: { // 注意:必须要on前缀 @@ -210,11 +214,35 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp } } }, + lastVars: { + title: "到期剩余", + type: "number", + form: { + show: false + }, + column: { + cellRender({ row }) { + if (!row.lastVars?.certExpiresTime) { + return "-"; + } + const leftDays = dayjs(row.lastVars.certExpiresTime).diff(dayjs(), "day"); + const color = leftDays < 20 ? "red" : "#389e0d"; + const percent = (leftDays / 90) * 100; + return `${leftDays} 天`} />; + }, + width: 110 + } + }, lastHistoryTime: { title: "最后运行", type: "datetime", form: { show: false + }, + column: { + sorter: true, + width: 120, + align: "center" } }, status: { @@ -225,6 +253,11 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp }), form: { show: false + }, + column: { + sorter: true, + width: 80, + align: "center" } }, @@ -242,6 +275,9 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp show: false }, column: { + sorter: true, + width: 80, + align: "center", component: { name: "fs-dict-switch", vModel: "checked" @@ -254,12 +290,25 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp } } }, + keepHistoryCount: { title: "历史记录保持数", type: "number", form: { value: 30, helper: "历史记录保持条数,多余的会被删除" + }, + column: { + show: false + } + }, + order: { + title: "排序号", + type: "number", + column: { + sorter: true, + align: "center", + width: 80 } }, createTime: { @@ -267,6 +316,11 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp type: "datetime", form: { show: false + }, + column: { + sorter: true, + width: 125, + align: "center" } }, updateTime: { @@ -274,6 +328,9 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp type: "datetime", form: { show: false + }, + column: { + show: false } } } diff --git a/packages/ui/certd-server/db/migration-pg/v10006__pipeline_title.sql b/packages/ui/certd-server/db/migration-pg/v10006__pipeline_title.sql index 92381b67..d2349dfd 100644 --- a/packages/ui/certd-server/db/migration-pg/v10006__pipeline_title.sql +++ b/packages/ui/certd-server/db/migration-pg/v10006__pipeline_title.sql @@ -1 +1,5 @@ alter table pi_pipeline alter column title type varchar(100) using title::varchar(100); +alter table pi_pipeline alter column content type text using content::text; +alter table pi_storage alter column value type text using value::text; + +alter table pi_pipeline add "order" integer default 0; diff --git a/packages/ui/certd-server/db/migration/v10006__pipeline_title.sql b/packages/ui/certd-server/db/migration/v10006__pipeline_title.sql index e69de29b..f2764e7f 100644 --- a/packages/ui/certd-server/db/migration/v10006__pipeline_title.sql +++ b/packages/ui/certd-server/db/migration/v10006__pipeline_title.sql @@ -0,0 +1,3 @@ +alter table pi_pipeline add COLUMN "order" integer default 0; + + diff --git a/packages/ui/certd-server/src/basic/base-service.ts b/packages/ui/certd-server/src/basic/base-service.ts index bd0ec77a..aa190924 100644 --- a/packages/ui/certd-server/src/basic/base-service.ts +++ b/packages/ui/certd-server/src/basic/base-service.ts @@ -118,10 +118,9 @@ export abstract class BaseService { } const qb = this.getRepository().createQueryBuilder('main'); if (order && order.prop) { - qb.orderBy('main.' + order.prop, order.asc ? 'ASC' : 'DESC'); - } else { - qb.orderBy('id', 'DESC'); + qb.addOrderBy('main.' + order.prop, order.asc ? 'ASC' : 'DESC'); } + qb.addOrderBy('id', 'DESC'); qb.offset(page.offset).limit(page.limit); //根据bean query if (query) { diff --git a/packages/ui/certd-server/src/basic/crud-controller.ts b/packages/ui/certd-server/src/basic/crud-controller.ts index 03ec9840..7a4fc964 100644 --- a/packages/ui/certd-server/src/basic/crud-controller.ts +++ b/packages/ui/certd-server/src/basic/crud-controller.ts @@ -9,12 +9,7 @@ export abstract class CrudController extends BaseController { @Body(ALL) body ) { - const pageRet = await this.getService().page( - body?.query, - body?.page, - body?.sort, - null - ); + const pageRet = await this.getService().page(body?.query, body?.page, body?.sort, null); return this.ok(pageRet); } @@ -54,6 +49,7 @@ export abstract class CrudController extends BaseController { await this.getService().update(bean); return this.ok(null); } + @Post('/delete') async delete( @Query('id') diff --git a/packages/ui/certd-server/src/modules/pipeline/controller/pipeline-controller.ts b/packages/ui/certd-server/src/modules/pipeline/controller/pipeline-controller.ts index 53007e3a..b86e7abd 100644 --- a/packages/ui/certd-server/src/modules/pipeline/controller/pipeline-controller.ts +++ b/packages/ui/certd-server/src/modules/pipeline/controller/pipeline-controller.ts @@ -23,9 +23,19 @@ export class PipelineController extends CrudController { @Post('/page', { summary: Constants.per.authOnly }) async page(@Body(ALL) body) { body.query.userId = this.ctx.user.id; + + const title = body.query.title; + delete body.query.title; + const buildQuery = qb => { - qb.where({}); + if (title) { + qb.where('title like :title', { title: `%${title}%` }); + } }; + if (!body.sort || !body.sort?.prop) { + body.sort = { prop: 'order', asc: false }; + } + return super.page({ ...body, buildQuery }); } @@ -48,7 +58,6 @@ export class PipelineController extends CrudController { await this.service.checkUserId(bean.id, this.ctx.user.id); } await this.service.save(bean); - await this.service.registerTriggerById(bean.id); return this.ok(bean.id); } diff --git a/packages/ui/certd-server/src/modules/pipeline/entity/pipeline.ts b/packages/ui/certd-server/src/modules/pipeline/entity/pipeline.ts index 6387a96b..50c5c0df 100644 --- a/packages/ui/certd-server/src/modules/pipeline/entity/pipeline.ts +++ b/packages/ui/certd-server/src/modules/pipeline/entity/pipeline.ts @@ -37,6 +37,16 @@ export class PipelineEntity { }) lastHistoryTime: number; + // 变量 + lastVars: any; + + @Column({ + name: 'order', + comment: '排序', + nullable: true, + }) + order: number; + @Column({ name: 'create_time', comment: '创建时间', diff --git a/packages/ui/certd-server/src/modules/pipeline/service/db-storage.ts b/packages/ui/certd-server/src/modules/pipeline/service/db-storage.ts index 9765d2e2..76ef7d2f 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/db-storage.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/db-storage.ts @@ -12,7 +12,7 @@ export class DbStorage implements IStorage { this.storageService = storageService; } - remove(scope: string, namespace: string, version: string, key: string): Promise { + async remove(scope: string, namespace: string, version: string, key: string): Promise { throw new Error('Method not implemented.'); } diff --git a/packages/ui/certd-server/src/modules/pipeline/service/pipeline-service.ts b/packages/ui/certd-server/src/modules/pipeline/service/pipeline-service.ts index a2c73afc..8ad742b8 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/pipeline-service.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/pipeline-service.ts @@ -47,8 +47,23 @@ export class PipelineService extends BaseService { return this.repository; } - async update(entity) { - await super.update(entity); + async page(query: any, page: { offset: number; limit: number }, order: any, buildQuery: any) { + const result = await super.page(query, page, order, buildQuery); + const pipelineIds: number[] = []; + const recordMap = {}; + for (const record of result.records) { + pipelineIds.push(record.id); + recordMap[record.id] = record; + } + const vars = await this.storageService.findPipelineVars(pipelineIds); + for (const varEntity of vars) { + const record = recordMap[varEntity.namespace]; + if (record) { + const value = JSON.parse(varEntity.value); + record.lastVars = value.value; + } + } + return result; } public async registerTriggerById(pipelineId) { @@ -71,10 +86,18 @@ export class PipelineService extends BaseService { return new PipelineDetail(pipeline); } + async update(bean: PipelineEntity) { + await this.clearTriggers(bean.id); + 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; await this.addOrUpdate(bean); + await this.registerTriggerById(bean.id); } /** @@ -153,6 +176,14 @@ export class PipelineService extends BaseService { } async delete(id: number) { + await this.clearTriggers(id); + //TODO 删除storage + // const storage = new DbStorage(pipeline.userId, this.storageService); + // await storage.remove(pipeline.id); + await super.delete([id]); + } + + async clearTriggers(id: number) { const pipeline = await this.info(id); if (!pipeline) { return; @@ -163,7 +194,6 @@ export class PipelineService extends BaseService { this.removeCron(id, trigger); } } - await super.delete([id]); } removeCron(pipelineId, trigger) { @@ -176,6 +206,7 @@ export class PipelineService extends BaseService { if (cron == null) { return; } + cron = cron.trim(); if (cron.startsWith('*')) { cron = '0' + cron.substring(1, cron.length); } @@ -183,7 +214,7 @@ export class PipelineService extends BaseService { this.cron.remove(name); this.cron.register({ name, - cron: cron, + cron, job: async () => { logger.info('定时任务触发:', pipelineId, trigger.id); try { @@ -198,6 +229,9 @@ export class PipelineService extends BaseService { async run(id: number, triggerId: string) { const entity: PipelineEntity = await this.info(id); + if (entity.disabled) { + return; + } const pipeline = JSON.parse(entity.content); if (!pipeline.stages || pipeline.stages.length === 0) { diff --git a/packages/ui/certd-server/src/modules/pipeline/service/storage-service.ts b/packages/ui/certd-server/src/modules/pipeline/service/storage-service.ts index 5469ef3c..2dbd8e22 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/storage-service.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/storage-service.ts @@ -1,6 +1,6 @@ import { Provide, Scope, ScopeEnum } from '@midwayjs/core'; import { InjectEntityModel } from '@midwayjs/typeorm'; -import { Repository } from 'typeorm'; +import { In, Repository } from 'typeorm'; import { BaseService } from '../../../basic/base-service.js'; import { StorageEntity } from '../entity/storage.js'; @@ -41,4 +41,14 @@ export class StorageService extends BaseService { } return; } + + async findPipelineVars(pipelineIds: number[]) { + return await this.repository.find({ + where: { + scope: 'pipeline', + namespace: In(pipelineIds), + key: 'vars', + }, + }); + } }