- CheckerDefinition 泛型化,HTTP/Command checker 移除 resolved target 断言 - 新增 ProbeStore.getAllRecentSamples 消除 targets 路由 N+1 查询 - 统一 getAllTargetStats 与 getTargetStats 的 availability 精度 - Engine rejected 结果写入 internal error 记录,提升可观测性 - 新增 bootstrap.ts 统一 dev/production 启动序列 - dataDir 相对路径改为基于配置文件目录解析 - validatePagination 增加 pageSize 上限 200 校验 - 修复 ErrorBoundary override 标记 - 更新 README/DEVELOPMENT 文档,新增完整测试覆盖
45 lines
2.5 KiB
Markdown
45 lines
2.5 KiB
Markdown
## ADDED Requirements
|
||
|
||
### 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 降序排列(最新在前)
|
||
|
||
## MODIFIED Requirements
|
||
|
||
### Requirement: targets 列表使用批量方法
|
||
`handleTargets`(routes/targets.ts 中生成 TargetStatus[] 的逻辑)SHALL 使用 `getLatestChecksMap`、`getAllTargetStats` 和 `getAllRecentSamples` 替代逐目标查询,消除 N+1 查询。
|
||
|
||
#### Scenario: 目标列表使用批量查询
|
||
- **WHEN** 处理 `GET /api/targets` 请求
|
||
- **THEN** 系统 SHALL 分别调用 `getLatestChecksMap()`、`getAllTargetStats()`、`getAllRecentSamples(30)` 批量获取数据,在内存中组装 TargetStatus 数组,而非对每个 target 逐条查询数据库
|
||
|
||
#### Scenario: 目标无采样数据
|
||
- **WHEN** 某 target 在 getAllRecentSamples 返回的 Map 中不存在
|
||
- **THEN** 该 target 的 recentSamples SHALL 为空数组
|
||
|
||
### Requirement: 批量查询目标统计
|
||
系统 SHALL 提供 `getAllTargetStats` 方法,通过单次 SQL GROUP BY 聚合查询获取所有 target 的拨测统计(totalChecks 和 availability)。availability 计算精度 SHALL 与 `getTargetStats` 一致,统一使用 `Math.round(value * 100) / 100` 保留两位小数。
|
||
|
||
#### Scenario: 获取所有目标的聚合统计
|
||
- **WHEN** 调用 `getAllTargetStats()`
|
||
- **THEN** 系统 SHALL 执行单次 GROUP BY 聚合查询,在内存中计算 availability 并返回 `Map<number, { totalChecks, availability }>`
|
||
|
||
#### Scenario: availability 精度
|
||
- **WHEN** 计算 availability(upCount / totalChecks * 100)
|
||
- **THEN** 结果 SHALL 使用 `Math.round(value * 100) / 100` 四舍五入保留两位小数,与 `getTargetStats` 方法一致
|
||
|
||
#### Scenario: 目标无历史记录
|
||
- **WHEN** 某 target 在 check_results 表中无任何记录
|
||
- **THEN** 该 target_id 在返回的 Map 中 SHALL 不存在对应的 key
|