1
0

feat: 实现分层架构,包含 domain、service、repository 和 pkg 层

- 新增 domain 层:model、provider、route、stats 实体
- 新增 service 层:models、providers、routing、stats 业务逻辑
- 新增 repository 层:models、providers、stats 数据访问
- 新增 pkg 工具包:errors、logger、validator
- 新增中间件:CORS、logging、recovery、request ID
- 新增数据库迁移:初始 schema 和索引
- 新增单元测试和集成测试
- 新增规范文档:config-management、database-migration、error-handling、layered-architecture、middleware-system、request-validation、structured-logging、test-coverage
- 移除 config 子包和 model_router(已迁移至分层架构)
This commit is contained in:
2026-04-16 00:47:20 +08:00
parent 915b004924
commit f18904af1e
77 changed files with 5727 additions and 1257 deletions

View File

@@ -1,10 +1,6 @@
# 用量统计
# Usage Statistics
## Purpose
TBD - 提供请求用量统计的记录和查询功能
## Requirements
## MODIFIED Requirements
### Requirement: 记录请求统计
@@ -22,15 +18,7 @@ TBD - 提供请求用量统计的记录和查询功能
- **THEN** 网关 SHALL 增加该供应商和模型的请求计数
- **THEN** 网关 SHALL 在流结束后记录统计
#### Scenario: 不记录失败请求
- **WHEN** 请求在到达供应商前失败(路由错误、验证错误)
- **THEN** 网关 SHALL NOT 增加请求计数
#### Scenario: 记录供应商错误
- **WHEN** 请求到达供应商但供应商返回错误
- **THEN** 网关 SHALL 仍然增加请求计数(请求已被处理)
**变更说明:** 统计记录通过 StatsService 调用,数据访问通过 StatsRepository。API 接口保持不变。
### Requirement: 按供应商查询统计
@@ -41,10 +29,7 @@ TBD - 提供请求用量统计的记录和查询功能
- **WHEN** 向 `/api/stats?provider_id=<provider_id>` 发送 GET 请求
- **THEN** 网关 SHALL 仅返回指定供应商的统计
#### Scenario: 查询不存在供应商的统计
- **WHEN** 向 `/api/stats?provider_id=<non_existent_id>` 发送 GET 请求
- **THEN** 网关 SHALL 返回空结果或零计数
**变更说明:** 通过 StatsService 和 StatsRepository 实现。API 接口保持不变。
### Requirement: 按模型查询统计
@@ -55,10 +40,7 @@ TBD - 提供请求用量统计的记录和查询功能
- **WHEN** 向 `/api/stats?model_name=<model_name>` 发送 GET 请求
- **THEN** 网关 SHALL 仅返回指定模型的统计
#### Scenario: 查询不存在模型的统计
- **WHEN** 向 `/api/stats?model_name=<non_existent_name>` 发送 GET 请求
- **THEN** 网关 SHALL 返回空结果或零计数
**变更说明:** 通过 StatsService 和 StatsRepository 实现。API 接口保持不变。
### Requirement: 按日期范围查询统计
@@ -70,20 +52,7 @@ TBD - 提供请求用量统计的记录和查询功能
- **THEN** 网关 SHALL 仅返回指定范围内的日期统计
- **THEN** 日期格式 SHALL 为 YYYY-MM-DD
#### Scenario: 不使用日期范围查询统计
- **WHEN** 向 `/api/stats` 发送 GET 请求,不带 start 和 end 参数
- **THEN** 网关 SHALL 返回所有可用日期的统计
#### Scenario: 仅使用开始日期查询统计
- **WHEN** 向 `/api/stats?start=<start_date>` 发送 GET 请求
- **THEN** 网关 SHALL 返回从开始日期到当前日期的统计
#### Scenario: 仅使用结束日期查询统计
- **WHEN** 向 `/api/stats?end=<end_date>` 发送 GET 请求
- **THEN** 网关 SHALL 返回从最早可用日期到结束日期的统计
**变更说明:** 通过 StatsService 和 StatsRepository 实现。API 接口保持不变。
### Requirement: 聚合统计
@@ -95,25 +64,7 @@ TBD - 提供请求用量统计的记录和查询功能
- **THEN** 网关 SHALL 为该天维护单条统计记录
- **THEN** 请求计数 SHALL 为所有请求的总和
#### Scenario: 跨多天请求
- **WHEN** 跨不同天发起请求
- **THEN** 网关 SHALL 为每一天维护独立的统计记录
### Requirement: 以结构化格式返回统计
网关 SHALL 以结构化 JSON 格式返回统计。
#### Scenario: 统计响应格式
- **WHEN** 查询统计
- **THEN** 响应 SHALL 为统计对象数组
- **THEN** 每个对象 SHALL 包含 provider_id, model_name, request_count 和 date
#### Scenario: 空统计
- **WHEN** 没有统计匹配查询条件
- **THEN** 网关 SHALL 返回空数组
**变更说明:** 聚合逻辑在 StatsRepository 中实现。API 接口保持不变。
### Requirement: 支持并发统计记录
@@ -125,31 +76,48 @@ TBD - 提供请求用量统计的记录和查询功能
- **THEN** 网关 SHALL 正确为每个请求增加请求计数
- **THEN** 不 SHALL 因并发写入而丢失统计
### Requirement: 仅将统计限制为请求计数
**变更说明:** 并发控制在 StatsRepository 中通过数据库事务实现。API 接口保持不变。
网关 SHALL 在 MVP 中仅记录请求计数,不记录其他指标。
## ADDED Requirements
#### Scenario: 仅请求计数
### Requirement: 使用 service 层处理业务逻辑
Handler SHALL 通过 StatsService 处理业务逻辑。
#### Scenario: 调用 service 方法
- **WHEN** handler 收到统计查询请求
- **THEN** SHALL 调用对应的 StatsService 方法Get、Aggregate
- **THEN** SHALL 使用 domain.UsageStats 类型
#### Scenario: 异步记录统计
- **WHEN** 请求完成需要记录统计
- **THEN** SHALL 异步调用 StatsService.Record()
- **THEN** SHALL 不阻塞响应返回
### Requirement: 使用 repository 层访问数据
Service SHALL 通过 StatsRepository 访问数据。
#### Scenario: 调用 repository 方法
- **WHEN** service 处理业务逻辑
- **THEN** SHALL 调用对应的 StatsRepository 方法
- **THEN** SHALL 使用 domain.UsageStats 类型
#### Scenario: 事务处理
- **WHEN** 记录统计
- **THEN** 网关 SHALL 仅跟踪请求数量
- **THEN** 网关 SHALL NOT 在 MVP 中跟踪 token 使用、成本、延迟或其他指标
- **THEN** SHALL 在 repository 层使用数据库事务
- **THEN** SHALL 确保并发安全
### Requirement: 为新组合初始化统计
### Requirement: 统计查询优化
网关 SHALL 为新的供应商-模型-日期组合自动创建统计记录
统计查询 SHALL 使用索引优化性能
#### Scenario: 组合的首次请求
#### Scenario: 使用索引
- **WHEN** 在新日期首次对供应商-模型组合发起请求
- **THEN** 网关 SHALL 创建新的统计记录request_count = 1
### Requirement: 查询所有统计
网关 SHALL 允许不带过滤条件查询所有统计。
#### Scenario: 查询所有统计
- **WHEN** 向 `/api/stats` 发送 GET 请求,不带任何查询参数
- **THEN** 网关 SHALL 返回所有可用统计
- **THEN** 结果 SHALL 按日期排序(最近的在前)
- **WHEN** 查询统计
- **THEN** SHALL 使用 (provider_id, model_name, date) 复合索引
- **THEN** SHALL 优化查询性能