- 合并 DEVELOPMENT.md 至 docs/development/README.md - 合并 CONTRIBUTING.md 至 docs/development/checker.md - 合并 build-release.md 至 release.md - 合并 testing-quality.md 内容至各专题文档 - 合并 status-model.md 至 expectations.md - 新增 docs/user/README.md 用户入口 - 简化 docs/README.md 文档路由 - 各专题文档新增适用场景和更新触发条件 - 更新 openspec/config.yaml 文档规则
8.6 KiB
后端开发
本文档说明 DiAL 后端的 API、配置加载、存储、拨测引擎、日志、expect 和错误模型开发约定。
适用场景:修改 src/server/、src/shared/api.ts、后端测试、配置契约、API 响应、store、engine、logger 或 expect 基础设施。
库使用优先级
| 优先级 | 来源 | 典型用途 |
|---|---|---|
| 1 | Bun 内置 API | Bun.serve、bun:sqlite、Bun.spawn、Bun.file、Bun.YAML |
| 2 | es-toolkit | 类型判断、深度比较、错误判断、并发控制、集合操作 |
| 3 | 标准 Web API | Object.fromEntries、Headers、fetch、AbortController |
| 4 | 主流三方库 | cheerio、xpath、@xmldom/xmldom |
| 5 | 自行实现 | 仅在以上都无法满足时 |
新增依赖前必须先检查上述每一层是否已有可用方案。
API 路由开发
路由文件位于 src/server/routes/,每个端点一个文件。路由通过 server.ts 的 Bun.serve({ routes }) 声明式注册,使用 per-method handler 对象。
新增路由步骤:
- 在
src/server/routes/下创建<name>.ts。 - 实现 handler 函数并 export。
- 在
server.ts的routes对象中注册路径和 method handler。 - 在
tests/server/app.test.ts中添加集成测试。
请求参数校验使用 middleware.ts 提供的 validateTargetId、validateTimeRange、validatePagination、validateDashboardWindow、validateRecentLimit、validateMetricsBucket。
共享 helpers
| 函数 | 用途 |
|---|---|
createApiError(error, status) |
构造 API 错误体 |
createHeaders(mode, init) |
创建响应 Headers,生产模式附加安全头 |
createHealthResponse() |
构造健康检查响应 |
formatDuration(ms) |
毫秒转为可读时长字符串 |
jsonResponse(body, options) |
JSON 响应构造 |
mapCheckResult(row, type) |
数据库行转 API CheckResult |
类型规范
- 共享类型以
src/shared/api.ts为唯一源头。 - 严格联合类型优先于宽类型。
- 存储层类型与 API 类型分离。
- checker 具体类型在各自目录定义,中间层通过 base interface 和 registry 完成类型擦除。
- 纯类型导入使用
import type。
配置契约与校验
配置加载流程固定为:unknown -> AuthoringProbeConfig -> NormalizedProbeConfig -> ValidatedProbeConfig -> ResolvedConfig。
| 层级 | 职责 |
|---|---|
| Authoring | 用户 YAML 可书写形态,允许变量引用和 expect 简写 |
| Normalized | 变量替换和 expect 简写展开后的契约校验形态 |
| Validated | 通过契约校验和语义校验的形态 |
| Resolved | checker resolve() 后的运行期配置 |
Ajv 保持严格拒绝模式:allErrors: true、不启用类型强制转换、不注入默认值、不自动删除未知字段。默认对象策略是 additionalProperties: false,只有明确的动态键值表可以开放任意键名。
新增或修改配置字段时必须同步更新 TypeBox schema fragments、probe-config.schema.json、语义 validator、测试和对应用户文档,并运行 bun run schema:check。
数据存储
存储层基于 bun:sqlite,WAL 模式运行,数据库文件位于配置的 dataDir 下。
| 方法 | 用途 |
|---|---|
syncTargets(targets) |
启动期同步 targets |
insertCheckResult() |
写入单条检查结果 |
getTargets() |
查询全部 targets |
getLatestChecksMap() |
批量获取每个 target 的最新检查结果 |
getAllTargetWindowStats(from, to) |
批量获取窗口基础计数 |
getDashboardIncidentStates(from, to) |
获取 Dashboard 窗口状态序列 |
getAllRecentSamples(limit) |
批量获取最近采样 |
getTargetCheckpoints(targetId, from, to) |
获取单目标窗口检查点序列 |
getTargetDurations(targetId, from, to) |
获取单目标成功耗时数组 |
getHistory() |
分页查询历史记录 |
prune(retentionMs) |
清理过期数据 |
数据库只负责存储、筛选、排序、分页、LIMIT 和基础聚合。指标语义在后端应用层实现。
拨测引擎
- 按 interval 分组,每组独立定时触发。
- 使用
es-toolkit/Semaphore限制全局最大并发数。 - 通过
checkerRegistry.get(target.type)选择 runner。 - 每次检查创建
AbortController并按target.timeoutMs触发 abort。 - 状态变化通过注入的
Logger输出结构化日志。
日志模块
后端运行时代码统一通过 Logger 接口输出日志,禁止直接使用 console.*。配置加载失败前使用 ConsoleFallbackLogger。
| 实现 | 用途 |
|---|---|
PinoLoggerWrapper |
生产运行时,封装 Pino、pino-pretty、pino-roll |
NoopLogger |
静默丢弃日志 |
MemoryLogger |
测试替身 |
ConsoleFallbackLogger |
配置加载失败前的降级日志 |
敏感信息会自动 redact authorization、cookie、set-cookie、authToken、key、password、token、apiKey 及其嵌套路径。
expect 系统
共享断言基础设施位于 src/server/checker/expect/。新增或修改 checker 的 expect 字段时,按以下原则选择模型:
| 模型 | 用途 | 典型字段 |
|---|---|---|
| enum / boolean | 状态类结果,结果集合小且稳定 | HTTP status、Cmd exitCode、TCP connected、UDP responded、ICMP alive |
ValueMatcher |
数字指标和字符串元数据 | durationMs、rowCount、finishReason、usage |
ContentExpectations |
返回内容或半结构化内容 | body、stdout、stderr、banner、response、output、result |
KeyedExpectations |
动态键值断言 | headers、DB rows 列值 |
详细 checker 开发流程见 Checker 开发。
错误模型
- API 错误:
{ error: "描述", status: <code> } - CheckFailure:
{ kind: "error" | "mismatch", phase, path, expected?, actual?, message }
expect 校验失败记录首个失败原因;网络、超时、进程崩溃统一为 kind: "error"。
后端测试与验证
| 变更类型 | 测试重点 |
|---|---|
| API 路由 | tests/server/app.test.ts 集成行为 |
| 配置 schema 或语义校验 | schema 导出、合法配置、非法配置 |
| store | SQLite 写入、查询、分页、聚合和清理 |
| engine | 调度、并发、超时、结果写入和状态变化日志 |
| expect 基础设施 | matcher 语义、快速失败、错误信息 |
| checker runner | 见 Checker 开发 |
后端运行时代码统一通过注入的 Logger 输出日志,禁止直接使用 console.*。新增或修改后端逻辑通常需要运行 bun run check;影响构建产物或前后端集成时运行 bun run verify。
更新触发条件
修改后端 API、共享类型、配置契约、store、engine、logger、expect 基础设施、错误模型或后端测试规范时,必须更新本文档。