1
0

chore: 归档 backend-architecture-hardening 变更并同步 delta spec 到主 spec

This commit is contained in:
2026-05-13 19:50:33 +08:00
parent 76b47006fe
commit a62007083d
15 changed files with 75 additions and 379 deletions

View File

@@ -17,7 +17,7 @@
- **THEN** 该 target_id 在返回的 Map 中 SHALL 不存在对应的 key
### Requirement: 批量查询目标统计
系统 SHALL 提供 `getAllTargetStats` 方法,通过单次 SQL GROUP BY 聚合查询获取所有 target 的拨测统计totalChecks 和 availability
系统 SHALL 提供 `getAllTargetStats` 方法,通过单次 SQL GROUP BY 聚合查询获取所有 target 的拨测统计totalChecks 和 availabilityavailability 计算精度 SHALL 与 `getTargetStats` 一致,统一使用 `Math.round(value * 100) / 100` 保留两位小数。
#### Scenario: 获取所有目标的聚合统计
- **WHEN** 调用 `getAllTargetStats()`
@@ -29,7 +29,7 @@
#### Scenario: availability 精度
- **WHEN** 计算 availabilityupCount / totalChecks * 100
- **THEN** 结果 SHALL 四舍五入保留两位小数
- **THEN** 结果 SHALL 使用 `Math.round(value * 100) / 100` 四舍五入保留两位小数,与 `getTargetStats` 方法一致
### Requirement: summary 查询使用批量方法
`getSummary` 方法 SHALL 使用 `getLatestChecksMap` 一次性获取所有 target 的最新检查结果,而非对每个 target 逐条查询。
@@ -39,11 +39,30 @@
- **THEN** 系统 SHALL 调用 `getLatestChecksMap()` 一次获取所有最新结果,在内存中遍历统计 up/down 数量,而非循环 N 次调用 `getLatestCheck()`
### Requirement: targets 列表使用批量方法
`createTargetsResponse`app.ts 中生成 TargetStatus[] 的逻辑SHALL 使用 `getLatestChecksMap``getAllTargetStats` 替代逐目标查询 latest checkout、stats 和 samples
`handleTargets`routes/targets.ts 中生成 TargetStatus[] 的逻辑SHALL 使用 `getLatestChecksMap``getAllTargetStats` `getAllRecentSamples` 替代逐目标查询,消除 N+1 查询
#### Scenario: 目标列表使用批量查询
- **WHEN** 处理 `GET /api/targets` 请求
- **THEN** 系统 SHALL 分别调用 `getLatestChecksMap()``getAllTargetStats()` 批量获取数据,在内存中组装 TargetStatus 数组,而非对每个 target 逐条查询数据库
- **THEN** 系统 SHALL 分别调用 `getLatestChecksMap()``getAllTargetStats()``getAllRecentSamples(30)` 批量获取数据,在内存中组装 TargetStatus 数组,而非对每个 target 逐条查询数据库
#### Scenario: 目标无采样数据
- **WHEN** 某 target 在 getAllRecentSamples 返回的 Map 中不存在
- **THEN** 该 target 的 recentSamples SHALL 为空数组
### Requirement: 批量查询所有目标的最近采样数据
系统 SHALL 提供 `getAllRecentSamples(limit: number)` 方法,通过单次 SQL 查询获取所有 target 的最近 N 条采样数据,返回 `Map<number, Array<{ timestamp: string; duration_ms: number | null; matched: number }>>` 结构。
#### Scenario: 获取所有目标的最近采样
- **WHEN** 调用 `getAllRecentSamples(30)`
- **THEN** 系统 SHALL 通过单次 SQL 查询获取每个 target 最近 30 条记录,返回按 target_id 索引的 Map
#### Scenario: 目标无历史记录
- **WHEN** 某 target 在 check_results 表中无任何记录
- **THEN** 该 target_id 在返回的 Map 中 SHALL 不存在对应的 key
#### Scenario: 采样数据排序
- **WHEN** 获取采样数据
- **THEN** 每个 target 的记录 SHALL 按 timestamp 降序排列(最新在前)
### Requirement: prepared statement 使用 query() 缓存
ProbeStore 中不涉及事务内复用的单次读/写操作 SHALL 使用 `this.db.query()` 而非 `this.db.prepare()`,利用 bun:sqlite 内置的 statement 缓存机制。