diff --git a/packages/core/pipeline/src/context/index.ts b/packages/core/pipeline/src/context/index.ts index 5fce2dfb6..726bb1057 100644 --- a/packages/core/pipeline/src/context/index.ts +++ b/packages/core/pipeline/src/context/index.ts @@ -35,7 +35,14 @@ export class Pager { } } -export async function doPageTurn(req: { pager: Pager; getPage: (pager: Pager) => Promise>; itemHandle?: (item: T) => Promise; batchHandle?: (pageRes: PageRes) => Promise }) { +export type PageTurnReq = { + pager: Pager; + getPage: (pager: Pager) => Promise>; + itemHandle?: (item: T) => Promise; + batchHandle?: (pageRes: PageRes) => Promise; +}; + +export async function doPageTurn(req: PageTurnReq) { let count = 0; const { pager, getPage, itemHandle, batchHandle } = req; while (true) { diff --git a/packages/ui/certd-server/src/modules/cert/service/task-executor.ts b/packages/ui/certd-server/src/modules/basic/service/task-executor.ts similarity index 83% rename from packages/ui/certd-server/src/modules/cert/service/task-executor.ts rename to packages/ui/certd-server/src/modules/basic/service/task-executor.ts index 73e4d9b87..a1899dfcc 100644 --- a/packages/ui/certd-server/src/modules/cert/service/task-executor.ts +++ b/packages/ui/certd-server/src/modules/basic/service/task-executor.ts @@ -59,19 +59,24 @@ export class BackTaskExecutor { delete task.run; } } + + + } export class BackTask { key: string; title: string; total: number = 0; current: number = 0; + skip: number = 0; startTime: number; endTime: number; status: string = "pending"; - error?: string; + errors?: string[] = []; timeoutId?: NodeJS.Timeout; + run: (task: BackTask) => Promise; constructor(opts:{ @@ -101,6 +106,31 @@ export class BackTask { incrementCurrent() { this.current++ } + + addError(error: string) { + logger.error(error) + this.errors.push(error) + } + + getSuccessCount() { + return this.current - this.errors.length + } + + getErrorCount() { + return this.errors.length + } + + getProgress() { + return (this.current / this.total * 1.0).toFixed(2) + } + + getSkipCount() { + return this.skip + } + + incrementSkip() { + this.skip++ + } } export const taskExecutor = new BackTaskExecutor(); \ No newline at end of file diff --git a/packages/ui/certd-server/src/modules/cert/service/domain-service.ts b/packages/ui/certd-server/src/modules/cert/service/domain-service.ts index 55d50df52..97aa28529 100644 --- a/packages/ui/certd-server/src/modules/cert/service/domain-service.ts +++ b/packages/ui/certd-server/src/modules/cert/service/domain-service.ts @@ -13,7 +13,7 @@ import { SubDomainsGetter } from '../../pipeline/service/getter/sub-domain-gette import { TaskServiceBuilder } from '../../pipeline/service/getter/task-service-getter.js'; import { SubDomainService } from "../../pipeline/service/sub-domain-service.js"; import { DomainEntity } from '../entity/domain.js'; -import { BackTask, taskExecutor } from './task-executor.js'; +import { BackTask, taskExecutor } from '../../basic/service/task-executor.js'; export interface SyncFromProviderReq { userId: number; @@ -208,9 +208,10 @@ export class DomainService extends BaseService { async doSyncFromProvider(req: SyncFromProviderReq) { + const key = `user_${req.userId || 0}` taskExecutor.start('syncFromProviderTask', new BackTask({ - key: `user_${req.userId}`, - title: `同步用户${req.userId}从域名提供商导入域名`, + key, + title: `从域名提供商导入域名(${key})`, run: async (task: BackTask) => { await this._syncFromProvider(req, task) }, @@ -254,6 +255,7 @@ export class DomainService extends BaseService { // } if (old) { //如果old存在,直接跳过 + task.incrementSkip() return } const updateObj: any = { @@ -279,22 +281,19 @@ export class DomainService extends BaseService { } } const batchHandle = async (pageRes: PageRes) => { - task.setTotal(pageRes.total || 0) + task.setTotal(pageRes.total || 0) } - const start = async () => { - await doPageTurn({ pager, getPage, itemHandle, batchHandle }) - logger.info(`同步用户(${req.userId ?? '全部'})从域名提供商${dnsProviderType}导入域名完成`) - } - - start() - + await doPageTurn({ pager, getPage, itemHandle, batchHandle }) + const key = `user_${userId || 0}` + logger.info(`从域名提供商${dnsProviderType}导入域名完成(${key}),共导入${task.current}个域名,跳过${task.getSkipCount()}个域名`) } async doSyncDomainsExpirationDate(req: { userId?: number }) { const userId = req.userId + const key = `user_${userId || 0}` taskExecutor.start('syncDomainsExpirationDateTask', new BackTask({ - key: `user_${userId}`, - title: `同步用户(${userId ?? '全部'})注册域名过期时间`, + key, + title: `同步注册域名过期时间(${key}))`, run: async (task: BackTask) => { await this._syncDomainsExpirationDate({ userId, task }) } @@ -326,13 +325,14 @@ export class DomainService extends BaseService { const parsed = parseDomainByPsl(domain) const mainDomain = parsed.domain || '' if (mainDomain !== domain) { - logger.warn(`${domain}为子域名,跳过同步`) + req.task.addError(`【${domain}】为子域名,跳过同步`) return } const suffix = parsed.tld || '' const rdapUrl = rdapMap[suffix] if (!rdapUrl) { - throw new Error(`未找到${suffix}的rdap地址`) + req.task.addError(`【${domain}】未找到${suffix}的rdap地址`) + return } // https://rdap.nic.work/domain/handsfree.work const rdap = await http.request({ @@ -354,7 +354,7 @@ export class DomainService extends BaseService { const query: any = { challengeType: "dns", } - if (req.userId!=null) { + if (req.userId != null) { query.userId = req.userId } const getDomainPage = async (pager: Pager) => { @@ -384,10 +384,10 @@ export class DomainService extends BaseService { } const { expirationDate, registrationDate } = res if (!expirationDate) { - logger.error(`获取域名${item.domain}过期时间失败`) + req.task.addError(`【${item.domain}】获取域名${item.domain}过期时间失败`) return } - logger.info(`更新域名${item.domain}过期时间:${dayjs(expirationDate).format('YYYY-MM-DD')}`) + logger.info(`【${item.domain}】更新域名过期时间:${dayjs(expirationDate).format('YYYY-MM-DD')}`) const updateObj: any = { id: item.id, expirationDate: expirationDate, @@ -396,13 +396,15 @@ export class DomainService extends BaseService { //更新 await super.update(updateObj) } catch (error) { - logger.error(`更新域名${item.domain}过期时间失败:${error}`) + const errorMsg = `【${item.domain}】${error.message ?? error}` + req.task.addError(errorMsg) } finally { await utils.sleep(1000) } } await doPageTurn({ pager, getPage: getDomainPage, itemHandle: itemHandle }) - logger.info(`同步用户(${req.userId ?? '全部'})注册域名过期时间完成`) + const key = `user_${req.userId || 'all'}` + logger.info(`同步用户(${key})注册域名过期时间完成(${req.task.getSuccessCount()}个成功,${req.task.errors.length}个失败)` ) } } diff --git a/packages/ui/certd-server/src/modules/cname/service/cname-record-service.ts b/packages/ui/certd-server/src/modules/cname/service/cname-record-service.ts index de7f5a3a2..123b9ff31 100644 --- a/packages/ui/certd-server/src/modules/cname/service/cname-record-service.ts +++ b/packages/ui/certd-server/src/modules/cname/service/cname-record-service.ts @@ -22,7 +22,7 @@ import punycode from "punycode.js"; import { SubDomainService } from "../../pipeline/service/sub-domain-service.js"; import { SubDomainsGetter } from "../../pipeline/service/getter/sub-domain-getter.js"; import { TaskServiceBuilder } from "../../pipeline/service/getter/task-service-getter.js"; -import { BackTask, taskExecutor } from "../../cert/service/task-executor.js"; +import { BackTask, taskExecutor } from "../../basic/service/task-executor.js"; type CnameCheckCacheValue = { validating: boolean;