perf: 修复检查全部某些情况下无效的bug,优化公共触发站点证书检查定时逻辑

This commit is contained in:
xiaojunnuo
2026-04-11 21:50:44 +08:00
parent 1e549dfd43
commit ee535895a3
7 changed files with 131 additions and 97 deletions
@@ -13,13 +13,11 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import parser from "cron-parser";
import { computed, ref } from "vue"; import { computed, ref } from "vue";
import dayjs from "dayjs";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { getCronNextTimes } from "/@/components/cron-editor/utils";
const { t } = useI18n(); const { t } = useI18n();
import { getCronNextTimes } from "/@/components/cron-editor/utils";
defineOptions({ defineOptions({
name: "CronEditor", name: "CronEditor",
}); });
@@ -121,7 +121,7 @@ export class SiteInfoController extends CrudController<SiteInfoService> {
@Post('/checkAll', { description: Constants.per.authOnly, summary: "检查所有站点监控" }) @Post('/checkAll', { description: Constants.per.authOnly, summary: "检查所有站点监控" })
async checkAll() { async checkAll() {
const { projectId, userId } = await this.getProjectUserIdWrite() const { projectId, userId } = await this.getProjectUserIdWrite()
await this.service.checkAllByUsers(userId,projectId); this.service.triggerJobOnce(userId,projectId);
return this.ok(); return this.ok();
} }
@@ -1,17 +1,18 @@
import {Autoload, Config, Init, Inject, Scope, ScopeEnum} from '@midwayjs/core'; import { logger } from '@certd/basic';
import {PipelineService} from '../pipeline/service/pipeline-service.js'; import { SysSettingsService, SysSiteInfo } from '@certd/lib-server';
import {logger} from '@certd/basic'; import { getPlusInfo, isPlus } from "@certd/plus-core";
import {SysSettingsService, SysSiteInfo} from '@certd/lib-server'; import { Autoload, Config, Init, Inject, Scope, ScopeEnum } from '@midwayjs/core';
import {SiteInfoService} from '../monitor/index.js';
import {Cron} from '../cron/cron.js';
import {UserSettingsService} from "../mine/service/user-settings-service.js";
import {UserSiteMonitorSetting} from "../mine/service/models.js";
import {getPlusInfo, isPlus} from "@certd/plus-core";
import dayjs from "dayjs"; import dayjs from "dayjs";
import {NotificationService} from "../pipeline/service/notification-service.js"; import { Between } from "typeorm";
import {UserService} from "../sys/authority/service/user-service.js";
import {Between} from "typeorm";
import { DomainService } from '../cert/service/domain-service.js'; import { DomainService } from '../cert/service/domain-service.js';
import { Cron } from '../cron/cron.js';
import { UserSiteMonitorSetting } from "../mine/service/models.js";
import { UserSettingsService } from "../mine/service/user-settings-service.js";
import { SiteInfoService } from '../monitor/index.js';
import { NotificationService } from "../pipeline/service/notification-service.js";
import { PipelineService } from '../pipeline/service/pipeline-service.js';
import { UserService } from "../sys/authority/service/user-service.js";
import { ProjectService } from '../sys/enterprise/service/project-service.js';
@Autoload() @Autoload()
@Scope(ScopeEnum.Request, { allowDowngrade: true }) @Scope(ScopeEnum.Request, { allowDowngrade: true })
@@ -47,6 +48,9 @@ export class AutoCRegisterCron {
@Inject() @Inject()
domainService: DomainService; domainService: DomainService;
@Inject()
projectService: ProjectService;
@Init() @Init()
@@ -72,9 +76,23 @@ export class AutoCRegisterCron {
async registerSiteMonitorCron() { async registerSiteMonitorCron() {
//先注册公共job //先注册公共job
await this.siteInfoService.registerSiteMonitorJob() logger.info(`注册公共站点证书检查定时任务`)
const randomMinute = Math.floor(Math.random() * 60)
this.cron.register({
name: 'siteMonitor',
cron: `0 ${randomMinute} 0 * * *`,
job:async ()=>{
logger.info(`开始公共站点证书检查任务`)
await this.siteInfoService.triggerCommonJob()
logger.info(`公共站点证书检查任务完成`)
},
});
logger.info(`注册公共站点证书检查定时任务完成`)
//注册用户独立的检查时间 //注册用户独立的检查时间
logger.info(`注册用户独立站点证书检查定时任务`)
const monitorSettingList = await this.userSettingsService.list({ const monitorSettingList = await this.userSettingsService.list({
query:{ query:{
key: UserSiteMonitorSetting.__key__, key: UserSiteMonitorSetting.__key__,
@@ -87,10 +105,11 @@ export class AutoCRegisterCron {
} }
await this.siteInfoService.registerSiteMonitorJob(item.userId,item.projectId) await this.siteInfoService.registerSiteMonitorJob(item.userId,item.projectId)
} }
logger.info(`注册用户独立站点证书检查定时任务完成`)
if (this.immediateTriggerSiteMonitor) { if (this.immediateTriggerSiteMonitor) {
logger.info(`立即触发一次站点证书检查任务`) logger.info(`立即触发一次公共站点证书检查任务`)
await this.siteInfoService.triggerJobOnce() await this.siteInfoService.triggerCommonJob()
} }
} }
@@ -1,5 +1,5 @@
import {Inject, Provide, Scope, ScopeEnum} from "@midwayjs/core"; import {Inject, Provide, Scope, ScopeEnum} from "@midwayjs/core";
import {BaseService, NeedSuiteException, NeedVIPException, SysSettingsService} from "@certd/lib-server"; import {BaseService, Constants, NeedSuiteException, NeedVIPException, SysSettingsService} from "@certd/lib-server";
import {InjectEntityModel} from "@midwayjs/typeorm"; import {InjectEntityModel} from "@midwayjs/typeorm";
import {In, Repository} from "typeorm"; import {In, Repository} from "typeorm";
import {SiteInfoEntity} from "../entity/site-info.js"; import {SiteInfoEntity} from "../entity/site-info.js";
@@ -19,6 +19,8 @@ import { dnsContainer } from "./dns-custom.js";
import { merge } from "lodash-es"; import { merge } from "lodash-es";
import { JobHistoryService } from "./job-history-service.js"; import { JobHistoryService } from "./job-history-service.js";
import { JobHistoryEntity } from "../entity/job-history.js"; import { JobHistoryEntity } from "../entity/job-history.js";
import { UserService } from "../../sys/authority/service/user-service.js";
import { ProjectService } from "../../sys/enterprise/service/project-service.js";
@Provide() @Provide()
@Scope(ScopeEnum.Request, {allowDowngrade: true}) @Scope(ScopeEnum.Request, {allowDowngrade: true})
@@ -44,6 +46,10 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
@Inject() @Inject()
jobHistoryService: JobHistoryService; jobHistoryService: JobHistoryService;
@Inject()
userService: UserService;
@Inject()
projectService: ProjectService;
@Inject() @Inject()
cron: Cron; cron: Cron;
@@ -353,18 +359,7 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
} }
} }
async checkAllByUsers(userId: any,projectId?: number) { async checkList(sites: SiteInfoEntity[]) {
if (userId==null) {
throw new Error("userId is required");
}
// const sites = await this.repository.find({
// where: {userId,projectId}
// });
// this.checkList(sites,false);
await this.triggerJobOnce(userId,projectId);
}
async checkList(sites: SiteInfoEntity[],isCommon: boolean) {
const cache = {} const cache = {}
const getFromCache = async (userId: number,projectId?: number) =>{ const getFromCache = async (userId: number,projectId?: number) =>{
const key = `${userId}_${projectId??""}` const key = `${userId}_${projectId??""}`
@@ -377,13 +372,6 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
} }
for (const site of sites) { for (const site of sites) {
const setting = await getFromCache(site.userId,site.projectId) const setting = await getFromCache(site.userId,site.projectId)
if (isCommon) {
//公共的检查,排除有设置cron的用户
if (setting?.cron) {
//设置了cron,跳过公共检查
continue;
}
}
let retryTimes = setting?.retryTimes let retryTimes = setting?.retryTimes
this.doCheck(site,true,retryTimes).catch(e => { this.doCheck(site,true,retryTimes).catch(e => {
logger.error(`检查站点证书失败,${site.domain}`, e.message); logger.error(`检查站点证书失败,${site.domain}`, e.message);
@@ -492,57 +480,73 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
} }
async registerSiteMonitorJob(userId?: number,projectId?: number) { async registerSiteMonitorJob(userId?: number,projectId?: number) {
const setting = await this.userSettingsService.getSetting<UserSiteMonitorSetting>(userId,projectId, UserSiteMonitorSetting);
if (!setting.cron) {
return;
}
//注册个人的 或项目的
this.cron.register({
name: `siteMonitor_${userId}_${projectId||""}`,
cron: setting.cron,
job: () => this.triggerJobOnce(userId,projectId),
});
}
if(userId == null){ async triggerCommonJob(){
//注册公共job //遍历用户
logger.info(`注册站点证书检查定时任务`) const userIds = await this.userService.getAllUserIds()
this.cron.register({ for (const userId of userIds) {
name: 'siteMonitor', const setting = await this.userSettingsService.getSetting<UserSiteMonitorSetting>(userId,null,UserSiteMonitorSetting)
cron: '0 0 0 * * *', if(setting && setting.cron){
job:async ()=>{ //该用户有自定义检查时间,跳过公共job
await this.triggerJobOnce() continue
},
});
logger.info(`注册站点证书检查定时任务完成`)
}else{
const setting = await this.userSettingsService.getSetting<UserSiteMonitorSetting>(userId,projectId, UserSiteMonitorSetting);
if (!setting.cron) {
return;
} }
//注册个人的 或项目的 await this.triggerJobOnce(userId)
this.cron.register({
name: `siteMonitor_${userId}_${projectId||""}`,
cron: setting.cron,
job: () => this.triggerJobOnce(userId,projectId),
});
} }
//遍历项目
const projectIds = await this.projectService.getAllProjectIds()
for (const projectId of projectIds) {
const userId = Constants.enterpriseUserId
const setting = await this.userSettingsService.getSetting<UserSiteMonitorSetting>(userId,projectId,UserSiteMonitorSetting)
if(setting && setting.cron){
//该项目有自定义检查时间,跳过公共job
continue
}
await this.triggerJobOnce(userId,projectId)
}
} }
async triggerJobOnce(userId?:number,projectId?:number) { async triggerJobOnce(userId?:number,projectId?:number) {
logger.info(`站点证书检查开始执行[${userId??'所有用户'}_${projectId??'所有项目'}]`); if(userId==null){
const query:any = { disabled: false }; throw new Error("userId is required");
let jobEntity :Partial<JobHistoryEntity> = null;
if(userId!=null){
query.userId = userId;
if(projectId){
query.projectId = projectId;
}
//判断是否已关闭
const setting = await this.userSettingsService.getSetting<UserSiteMonitorSetting>(userId,projectId, UserSiteMonitorSetting);
if (setting && !setting.cron) {
return;
}
jobEntity = {
userId,
projectId,
type:"siteCertMonitor",
title: '站点证书检查',
result:"start",
startAt:new Date().getTime(),
}
await this.jobHistoryService.add(jobEntity);
} }
const query:any = { disabled: false };
query.userId = userId;
if(projectId){
query.projectId = projectId;
}
const siteCount = await this.repository.count({
where: query,
});
if (siteCount === 0) {
logger.info(`用户/项目[${userId}_${projectId||""}]没有站点证书需要检查`)
return;
}
logger.info(`站点证书检查开始执行[${userId}_${projectId||""}]`);
let jobEntity :Partial<JobHistoryEntity> = null;
jobEntity = {
userId,
projectId,
type:"siteCertMonitor",
title: '站点证书检查',
result:"start",
startAt:new Date().getTime(),
}
await this.jobHistoryService.add(jobEntity);
let offset = 0; let offset = 0;
const limit = 50; const limit = 50;
let count = 0; let count = 0;
@@ -557,21 +561,18 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
break; break;
} }
offset += records.length; offset += records.length;
const isCommon = !userId;
count += records.length; count += records.length;
await this.checkList(records,isCommon); await this.checkList(records);
} }
logger.info(`站点证书检查完成[${userId??'所有用户'}_${projectId??'所有项目'}]`); logger.info(`站点证书检查完成[${userId}_${projectId||""}]`);
if(jobEntity){ await this.jobHistoryService.update({
await this.jobHistoryService.update({ id: jobEntity.id,
id: jobEntity.id, result: "done",
result: "done", content:`共检查${count}个站点`,
content:`共检查${count}个站点`, endAt:new Date().getTime(),
endAt:new Date().getTime(), updateTime:new Date(),
updateTime:new Date(), });
});
}
} }
async batchDelete(ids: number[], userId: number,projectId?:number): Promise<void> { async batchDelete(ids: number[], userId: number,projectId?:number): Promise<void> {
@@ -320,8 +320,6 @@ export class SiteIpService extends BaseService<SiteIpEntity> {
for (const item of list) { for (const item of list) {
await this.add(item); await this.add(item);
} }
// await this.checkAllByUsers(req.userId);
}; };
await batchAdd(list); await batchAdd(list);
} }
@@ -400,7 +400,15 @@ export class UserService extends BaseService<UserEntity> {
id: userId, id: userId,
...body, ...body,
}) })
}
async getAllUserIds() {
const users = await this.repository.find({
select: ['id'],
where: {
status: 1,
},
})
return users.map(item => item.id);
} }
} }
@@ -284,4 +284,14 @@ export class ProjectService extends BaseService<ProjectEntity> {
return project?.isSystem ?? false; return project?.isSystem ?? false;
} }
async getAllProjectIds() {
const projects = await this.repository.find({
select: ['id'],
where: {
disabled: false,
},
})
return projects.map(item => item.id);
}
} }