refactor: 把 /derivatives 的多源编排从 controller 搬进 usecase
为什么:原 controller handler 在 HTTP 层同时承担了 4 项 usecase 职责 (多源拼装、错误降级策略、limit 硬编码、响应结构组装),违反了 "controller 只做参数解析 + 调用 + 序列化" 的边界。等后续给衍生品加 缓存 / taker volume / 数据质量字段时,HTTP 层会持续变厚。 改动: - 新增 internal/usecase/market_query.go: MarketQueryUsecase.GetDerivatives() 并发拉 current funding/OI + 串行查历史 + 错误聚合为 warnings 返回 - /derivatives handler 退化到 4 行;MarketDeps / restapi.Deps 同步收窄 - /klines 保持直查 KlineRepo(thin query,G11 例外) - 新增 G11 守卫:grep "FundingRepo|OIRepo|LSRepo|TakerRepo" internal/controller 破坏性 API 变更(/derivatives 响应): - 删除 funding.error / openInterest.error - 新增顶层 warnings: []string 顶层 symbol / funding / openInterest / longShortRatio / takerBuySellVolume 保持。 harness 同步: - AGENTS.md §6 加 G11 grep - ai/project-map.md 加 market_query.go + /derivatives 数据流分支 - ai/task-templates.md T6 加"破坏性变体"分支(本次重构暴露了原假设过严) - ai/harness-health.md W1 记一次轻量验证 + 守卫数 10→11 验收: go build / go vet / G6 grep / G11 grep 全绿。
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
| 验证命令可跑 | strong | Makefile 全部命令在 README + AGENTS.md 双重列出 |
|
||||
| 快速反馈环路 | strong | `go build ./...` < 2s,`go vet ./...` < 1s,单包测试支持 |
|
||||
| 任务契约质量 | partial | 模板已写(`ai/task-templates.md`),但还没有真实任务用过 |
|
||||
| 守卫规则清晰度 | strong | 10 条 G1-G10,每条都有可机械验证命令 |
|
||||
| 守卫规则清晰度 | strong | 11 条 G1-G11,每条都有可机械验证命令 |
|
||||
| 架构决策耐久度 | strong | ADR 0001 记录 9 条核心决策;其他 ADR 等触发 |
|
||||
| Spec / test-plan | partial | 还没有 specs/,因为 v1 没有需要 spec 的任务;v2 新数据源时必填 |
|
||||
| 失败反馈环路 | partial | AGENTS.md §10 写了升级时机,但还没有 `ai/risk-guardrails.md` 改动史可参考 |
|
||||
@@ -44,6 +44,7 @@
|
||||
**现状**:模板已写完,但没有 PR 用过这些契约。
|
||||
**影响**:模板可能太严格或太松。
|
||||
**纠正时机**:完成第一个非平凡 PR(比如 Milestone 6 的技术指标)后回看,调整模板。
|
||||
**2026-05-24 更新**:`/derivatives` controller→usecase 重构(抽 `MarketQueryUsecase`、新增 G11)算一次轻量验证。发现 T6 "API 响应字节级一致" 假设过严——抽离 usecase 时合理地把 sub-object `error` 字段升级成顶层 `warnings` 数组,已在 T6 加"破坏性变体"分支。Milestone 6 真正落地时再做一次完整复评。
|
||||
|
||||
### W2. 还没有 work-status.md
|
||||
**现状**:目前是单 agent / 单会话工作,不需要 work-status 协调。
|
||||
|
||||
@@ -82,6 +82,7 @@ Clean Architecture 四层。**依赖方向单向:`controller → usecase → e
|
||||
- `DerivativesProvider`(funding/OI/多空比/taker volume 共 7 个方法)
|
||||
- `KlineRepository` / `FundingRepository` / `OpenInterestRepository` / `LongShortRatioRepository` / `TakerVolumeRepository`
|
||||
- `market_context.go`:聚合 `/v1/market/context`。errgroup 并发拉 snapshot/funding/OI,DB K 线不足 200 根回源 Binance 补,异步写回。
|
||||
- `market_query.go`:`/v1/market/derivatives` 后端。`GetDerivatives(symbol, period)` 并发拉 current funding/OI + 串行查 funding/OI/多空比历史,错误降级为 warnings 返回。
|
||||
|
||||
**约束**(grep 可验证):
|
||||
```bash
|
||||
@@ -98,8 +99,9 @@ usecase 不可直接 import 任何具体实现。新增业务流程 → 在 `por
|
||||
**约束**:
|
||||
```bash
|
||||
grep -r "repo/webapi/binance\|repo/persistent" internal/controller # 必须无输出
|
||||
grep -rn "FundingRepo\|OIRepo\|LSRepo\|TakerRepo" internal/controller # 必须无输出(G11)
|
||||
```
|
||||
controller 只能依赖 usecase 和 entity,不能直接调 binance client 或 postgres repo。
|
||||
controller 只能依赖 usecase 和 entity,不能直接调 binance client 或 postgres repo。衍生品多源查询必须经 usecase(详见 `ai/risk-guardrails.md` G11)。`KlineRepo` 暂时允许直查 `/klines`,因为它现在是 thin query。
|
||||
|
||||
**扩展点**:新增路由 → 加 handler → 通过 `MarketDeps` 注入依赖(不要直接 import repo 包)。
|
||||
|
||||
@@ -191,13 +193,19 @@ cron tick
|
||||
```
|
||||
HTTP request
|
||||
└→ internal/controller/restapi/v1/market_routes.go
|
||||
└→ usecase.MarketContext.Build
|
||||
├→ marketData.GetTicker24h ┐
|
||||
├→ derivatives.GetCurrent… ├ errgroup 并发
|
||||
├→ derivatives.GetCurrent… ┘
|
||||
├→ klineRepo.FindRecent × 5 周期
|
||||
│ └ DB 不足 → 回源 binance.GetKlines(异步写回)
|
||||
└→ fundingRepo / oiRepo / lsRepo.FindRecent
|
||||
├→ /context → usecase.MarketContext.Build
|
||||
│ ├→ marketData.GetTicker24h ┐
|
||||
│ ├→ derivatives.GetCurrent… ├ errgroup 并发
|
||||
│ ├→ derivatives.GetCurrent… ┘
|
||||
│ ├→ klineRepo.FindRecent × 5 周期
|
||||
│ │ └ DB 不足 → 回源 binance.GetKlines(异步写回)
|
||||
│ └→ fundingRepo / oiRepo / lsRepo.FindRecent
|
||||
├→ /derivatives → usecase.MarketQuery.GetDerivatives
|
||||
│ ├→ derivatives.GetCurrentFunding ┐ errgroup
|
||||
│ ├→ derivatives.GetCurrentOI ┘
|
||||
│ └→ fundingRepo / oiRepo / lsRepo.FindRecent
|
||||
├→ /klines → klineRepo.FindRecent(thin query,允许直查)
|
||||
└→ /snapshot → marketData.GetTicker24h
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -177,6 +177,22 @@ grep -rn --include="*.go" "websocket\|fstream.binance" .
|
||||
|
||||
---
|
||||
|
||||
## G11. Controller 不编排 derivatives 多源查询
|
||||
|
||||
**规则**:`internal/controller/**` 不得直接持有或调用 `FundingRepository` / `OpenInterestRepository` / `LongShortRatioRepository` / `TakerVolumeRepository`。这类衍生品历史数据的"查哪些表 + 多源拼装 + 错误降级 → warnings"必须在 `internal/usecase/` 完成,controller 只做参数解析、调用 usecase、返回 JSON。
|
||||
|
||||
**为什么**:曾经 `/derivatives` handler 一次性编排了 6 处查询、4 个静默吞错的 `_`、硬编码的 limit 和响应结构——HTTP 层在替业务层做决定。要给衍生品加 taker volume、缓存、降级策略、数据质量 warnings 时,应该只动 usecase,不该让 HTTP handler 跟着变厚。
|
||||
|
||||
**例外**:`KlineRepository` 暂时允许 controller 直查,因为 `/klines` 现在就是 thin query。一旦它要加缓存 / live fallback / interval 聚合,就同样要搬进 usecase。
|
||||
|
||||
**怎么验证**:
|
||||
```bash
|
||||
grep -rn "FundingRepo\|OIRepo\|LSRepo\|TakerRepo" internal/controller
|
||||
# 期望:无输出
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 升级守护规则的时机
|
||||
|
||||
同一类错误第二次出现 → 写一条新规则进来。修改本文件 = 改动了项目契约,需要在 PR 描述里说明原因并 @ 维护者。
|
||||
|
||||
@@ -159,14 +159,18 @@ acceptance:
|
||||
objective: <消除哪个边界违反 / 抽取哪段重复>
|
||||
scope: <文件列表>
|
||||
out-of-scope:
|
||||
- 不改行为(API 响应字节级一致 / DB schema 不变)
|
||||
constraints: G6
|
||||
- 行为变化(默认:API 响应字节级一致 / DB schema 不变)
|
||||
- 例外:如果重构本身是为了把不该在 controller 的"错误降级 / 响应组装"搬进 usecase,
|
||||
可以一并修响应契约(如 sub-object 的 error 字段聚合为顶层 warnings)。
|
||||
必须在 acceptance 显式标 "破坏性",并在 PR 描述列出旧 → 新字段映射。
|
||||
constraints: G6 + G11(如果动 controller)
|
||||
validation:
|
||||
- go build ./... && go vet ./...
|
||||
- 全部 grep 边界检查(AGENTS.md §6)
|
||||
- make test
|
||||
acceptance:
|
||||
- diff 中不含行为变化(只是搬代码 / 重命名 / 抽接口)
|
||||
- 默认:diff 中不含行为变化(只是搬代码 / 重命名 / 抽接口)
|
||||
- 破坏性变体:列出响应字段变化,确认上游(Hermes)消费方已知或不受影响
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user