feat: 接入 CoinGlass 清算热力图隔离链路
Some checks failed
ci / build + vet + guard + race (push) Has been cancelled

This commit is contained in:
dela
2026-05-25 16:57:22 +08:00
parent e5fb54cb72
commit 1b61541ff5
32 changed files with 2550 additions and 70 deletions

View File

@@ -179,9 +179,9 @@ grep -rn --include="*.go" "websocket\|fstream.binance" .
## G11. Controller 不编排 derivatives 多源查询
**规则**`internal/controller/**` 不得直接持有或调用 `FundingRepository` / `OpenInterestRepository` / `LongShortRatioRepository` / `TakerVolumeRepository`。这类衍生品历史数据的"查哪些表 + 多源拼装 + 错误降级 → warnings"必须在 `internal/usecase/` 完成controller 只做参数解析、调用 usecase、返回 JSON。
**规则**`internal/controller/**` 不得直接持有或调用 `FundingRepository` / `OpenInterestRepository` / `LongShortRatioRepository` / `TakerVolumeRepository` / `CoinglassRepository`。这类衍生品历史数据的"查哪些表 + 多源拼装 + 错误降级 → warnings"必须在 `internal/usecase/` 完成controller 只做参数解析、调用 usecase、返回 JSON。
**为什么**:曾经 `/derivatives` handler 一次性编排了 6 处查询、4 个静默吞错的 `_`、硬编码的 limit 和响应结构——HTTP 层在替业务层做决定。要给衍生品加 taker volume、缓存、降级策略、数据质量 warnings 时,应该只动 usecase不该让 HTTP handler 跟着变厚。
**为什么**:曾经 `/derivatives` handler 一次性编排了 6 处查询、4 个静默吞错的 `_`、硬编码的 limit 和响应结构——HTTP 层在替业务层做决定。要给衍生品加 taker volume、缓存、降级策略、数据质量 warnings 时,应该只动 usecase不该让 HTTP handler 跟着变厚。CoinGlass 接入沿用同款约束v3-PR-1 起)。
**例外**`KlineRepository` 暂时允许 controller 直查,因为 `/klines` 现在就是 thin query。一旦它要加缓存 / live fallback / interval 聚合,就同样要搬进 usecase。
@@ -189,22 +189,26 @@ grep -rn --include="*.go" "websocket\|fstream.binance" .
```bash
grep -rn "FundingRepo\|OIRepo\|LSRepo\|TakerRepo" internal/controller
# 期望:无输出
grep -rn "CoinglassRepo\|coinglassRepo" internal/controller
# 期望无输出G11.2,由 make guard 自动跑)
```
---
## G12. 指标计算的 float64 边界
**规则**`float64``internal/usecase/` 下**只允许出现在纯解析 usecase 文件**(当前为 `indicator.go``derivatives_signal.go`)内部作为 transient 计算变量;进入 `entity` / 返回上层之前必须 `strconv.FormatFloat(_, 'f', -1, 64)` 转回 string。这些文件同时**禁止** import `internal/repo/...` 的任何子包。
**规则**`float64``internal/usecase/` 下**只允许出现在纯解析 usecase 文件**(当前为 `indicator.go``derivatives_signal.go``coinglass_signal.go`)内部作为 transient 计算变量;进入 `entity` / 返回上层之前必须 `strconv.FormatFloat(_, 'f', -1, 64)` 转回 string。这些文件同时**禁止** import `internal/repo/...` 的任何子包。
**为什么**G2 已经预留"指标计算中间过程可用 float64"的例外但没有可机械验证的边界。Milestone 6 之后会有更多指标和衍生品信号加入,必须把例外明文化、可 grep 化,避免某天 float64 悄悄出现在 entity 字段或被 repo 持久化。决策细节`ai/adr/0002-indicator-numeric-boundary.md`
`internal/repo/webapi/coinglass/mapper.go`webapi 层)允许 transient `float64`(解 JSON number 默认 float64不在 G12.1 grep 路径内;其安全边界靠 G12.4entity 全 stringCoinGlass entity 严格沿用 ADR-0001 D5+ `mapper_test.go` table-driven 双兜底。详`ai/adr/0004-coinglass-numeric-boundary-extension.md` D3
**新增同形态文件时**:必须同步扩 Makefile 的 G12.1 白名单与 G12.5/6 子规则(参考 `derivatives_signal.go` 接入的方式),并把文件名加入本规则的"当前为"括注
**为什么**G2 已经预留"指标计算中间过程可用 float64"的例外但没有可机械验证的边界。Milestone 6 之后会有更多指标和衍生品信号加入,必须把例外明文化、可 grep 化,避免某天 float64 悄悄出现在 entity 字段或被 repo 持久化。决策细节见 `ai/adr/0002-indicator-numeric-boundary.md``ai/adr/0004-coinglass-numeric-boundary-extension.md`
**新增同形态文件时**:必须同步扩 Makefile 的 G12.1 白名单与 G12.5/6/7/8 子规则(参考 `derivatives_signal.go``coinglass_signal.go` 接入的方式),并把文件名加入本规则的"当前为"括注。**只有 ADR 批准过的形态可以加 token**ADR-0004 决策)。
**怎么验证**(由 `make guard` 自动跑):
```bash
# G12.1usecase 下除白名单文件外不得出现 float64
grep -rn --include="*.go" "float64\|float32" internal/usecase | grep -vE "indicator|derivatives_signal"
grep -rn --include="*.go" "float64\|float32" internal/usecase | grep -vE "indicator|derivatives_signal|coinglass"
# 期望:无输出
# G12.2/G12.3indicator.go 不得 import repo 子包,也不得 import binance/postgres/pgx
@@ -217,6 +221,11 @@ grep -n "internal/repo" internal/usecase/derivatives_signal.go
grep -nE "binance|postgres|pgx" internal/usecase/derivatives_signal.go
# 期望:无输出
# G12.7/G12.8coinglass_signal.go 同上(文件不存在时空跑)
grep -n "internal/repo" internal/usecase/coinglass_signal.go
grep -nE "binance|postgres|pgx" internal/usecase/coinglass_signal.go
# 期望:无输出
# G12.4entity 字段任何位置不得 float
grep -rn --include="*.go" "float64\|float32" internal/entity
# 期望:无输出