From 72b65978175427bd8359b57963cbb2eb6dd1ca0c Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Tue, 5 May 2026 22:17:09 +0800 Subject: [PATCH] chore: agents update --- AGENTS.md | 3 +- .../modules/cert/service/tld-client.test.ts | 43 +++++++++++++++++++ .../src/modules/cert/service/tld-client.ts | 4 +- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index bcb223cc9..030d502d8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -106,7 +106,7 @@ Certd 是一个支持私有化部署的 SSL/TLS 证书自动化管理平台。 - 前端 `pnpm dev`:启动 Vite 开发服务 - 前端 `pnpm build`:生产构建 - 前端 `pnpm tsc`:类型检查 -- 前端 `pnpm test:unit`:Vitest 单元测试 +- 前端暂不跑单元测试;当前 `test:unit` 只是占位脚本 ## 流水线与插件模型 @@ -207,5 +207,6 @@ Get-ChildItem packages\ui\certd-client\src\views\certd - 实现新功能或修复行为缺陷前,先补对应单元测试,并先运行测试确认它处于失败状态;再实现功能或修复代码,反复运行聚焦单元测试直到通过。若某项改动确实不适合先写单元测试,应在回复中说明原因和替代验证方式。 - 后补单元测试时,应先基于对正确行为的实际预期编写测试,而不是为了迎合现有实现改写预期;如果运行后出现红灯,且通过测试需要修改已有实现,应先向用户确认这是确实的 bug,还是原本需求/既有行为就是如此;确认后再修改原始实现,避免把测试补充变成未经确认的行为改动。 - 后端纯单元测试用例放在 `src` 目录内,并尽量与被测文件相邻,例如 `src/utils/random.test.ts`;对应 `test:unit` 只跑 `src/**/*.test.ts`,构建/打包配置应排除这些 `*.test.ts` 文件。 +- 单个 monorepo 包运行单元测试时,优先使用 `corepack pnpm --dir <包目录> test:unit`,例如 `corepack pnpm --dir packages\ui\certd-server test:unit`、`corepack pnpm --dir packages\core\basic test:unit`、`corepack pnpm --dir packages\plugins\plugin-lib test:unit`;也可以用包名过滤,例如 `corepack pnpm --filter @certd/ui-server test:unit`。前端 `packages\ui\certd-client` 暂时不跑单元测试。 - 前端 TS/Vue/locale 等文件改动后,优先只对本次改动文件运行项目现有自动格式化/修复,例如 `corepack pnpm --dir packages\ui\certd-client exec prettier --write ` 和 `corepack pnpm --dir packages\ui\certd-client exec eslint --fix `;不要为了格式化无关文件而扩大 diff。项目保留了 `tslint` 依赖,但当前主要使用 ESLint + Prettier。 - 优先对改动包运行聚焦的测试或类型检查;只有跨包影响明显时再考虑全 monorepo 构建。 diff --git a/packages/ui/certd-server/src/modules/cert/service/tld-client.test.ts b/packages/ui/certd-server/src/modules/cert/service/tld-client.test.ts index be60bcf30..b0a961b10 100644 --- a/packages/ui/certd-server/src/modules/cert/service/tld-client.test.ts +++ b/packages/ui/certd-server/src/modules/cert/service/tld-client.test.ts @@ -80,4 +80,47 @@ describe("TldClient", () => { (TldClient as any).rdapSsRequestTimes = originalRequestTimes; } }); + + it("clears rdapSsRequestTimes entries older than 24 hours", async () => { + const now = Date.now(); + const originalRequestTimes = (TldClient as any).rdapSsRequestTimes; + + try { + const recentTime = now - 1000 * 60 * 60; + const oldTime = now - 25 * 60 * 60 * 1000; + + (TldClient as any).rdapSsRequestTimes = [oldTime, recentTime]; + + const client = new TldClient() as any; + await client.waitRdapSsRateLimit(); + + const times = (TldClient as any).rdapSsRequestTimes; + assert.equal(times.length, 2); + assert.ok(times.every((t: number) => now - t < 24 * 60 * 60 * 1000)); + } finally { + (TldClient as any).rdapSsRequestTimes = originalRequestTimes; + } + }); + + it("keeps rdapSsRequestTimes entries within 24 hours and removes those exactly at boundary", async () => { + const now = Date.now(); + const originalRequestTimes = (TldClient as any).rdapSsRequestTimes; + + try { + const boundaryTime = now - 24 * 60 * 60 * 1000; + const withinTime = now - 23 * 60 * 60 * 1000; + + (TldClient as any).rdapSsRequestTimes = [boundaryTime, withinTime]; + + const client = new TldClient() as any; + await client.waitRdapSsRateLimit(); + + const times = (TldClient as any).rdapSsRequestTimes as number[]; + assert.equal(times.length, 2); + assert.ok(times.every((t: number) => now - t < 24 * 60 * 60 * 1000)); + assert.ok(times.includes(withinTime)); + } finally { + (TldClient as any).rdapSsRequestTimes = originalRequestTimes; + } + }); }); diff --git a/packages/ui/certd-server/src/modules/cert/service/tld-client.ts b/packages/ui/certd-server/src/modules/cert/service/tld-client.ts index 6681ad533..cfd3f4a86 100644 --- a/packages/ui/certd-server/src/modules/cert/service/tld-client.ts +++ b/packages/ui/certd-server/src/modules/cert/service/tld-client.ts @@ -18,6 +18,7 @@ export class TldClient { { windowMs: 24 * 60 * 60 * 1000, max: 12000 }, ]; private static readonly RDAP_SS_MAX_WAIT_MS = 3 * 60 * 1000; + private static readonly RDAP_SS_DATA_RETENTION_MS = 24 * 60 * 60 * 1000; private static rdapSsRequestTimes: number[] = []; private rdapMap: Record = {}; @@ -177,8 +178,7 @@ export class TldClient { private async waitRdapSsRateLimit() { while (true) { const now = Date.now(); - const maxWindowMs = Math.max(...TldClient.RDAP_SS_RATE_LIMITS.map(item => item.windowMs)); - TldClient.rdapSsRequestTimes = TldClient.rdapSsRequestTimes.filter(time => now - time < maxWindowMs); + TldClient.rdapSsRequestTimes = TldClient.rdapSsRequestTimes.filter(time => now - time < TldClient.RDAP_SS_DATA_RETENTION_MS); const waitMs = TldClient.RDAP_SS_RATE_LIMITS.reduce((maxWaitMs, limit) => { const times = TldClient.rdapSsRequestTimes.filter(time => now - time < limit.windowMs);