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:
113
internal/usecase/market_query.go
Normal file
113
internal/usecase/market_query.go
Normal file
@@ -0,0 +1,113 @@
|
||||
package usecase
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"cryptoHermes/internal/entity"
|
||||
)
|
||||
|
||||
const (
|
||||
derivativesFundingHistoryLen = 100
|
||||
derivativesOIHistoryLen = 200
|
||||
derivativesLongShortLen = 200
|
||||
)
|
||||
|
||||
type MarketQueryUsecase struct {
|
||||
derivatives DerivativesProvider
|
||||
fundingRepo FundingRepository
|
||||
oiRepo OpenInterestRepository
|
||||
lsRepo LongShortRatioRepository
|
||||
}
|
||||
|
||||
func NewMarketQueryUsecase(
|
||||
derivatives DerivativesProvider,
|
||||
fundingRepo FundingRepository,
|
||||
oiRepo OpenInterestRepository,
|
||||
lsRepo LongShortRatioRepository,
|
||||
) *MarketQueryUsecase {
|
||||
return &MarketQueryUsecase{
|
||||
derivatives: derivatives,
|
||||
fundingRepo: fundingRepo,
|
||||
oiRepo: oiRepo,
|
||||
lsRepo: lsRepo,
|
||||
}
|
||||
}
|
||||
|
||||
func (u *MarketQueryUsecase) GetDerivatives(ctx context.Context, symbol, period string) (*entity.DerivativesBundle, []string, error) {
|
||||
var (
|
||||
currentFund *entity.FundingRate
|
||||
currentOI *entity.OpenInterest
|
||||
warnMu sync.Mutex
|
||||
warnings []string
|
||||
)
|
||||
addWarn := func(w string) {
|
||||
warnMu.Lock()
|
||||
warnings = append(warnings, w)
|
||||
warnMu.Unlock()
|
||||
}
|
||||
|
||||
g, gctx := errgroup.WithContext(ctx)
|
||||
g.Go(func() error {
|
||||
f, err := u.derivatives.GetCurrentFunding(gctx, symbol)
|
||||
if err != nil {
|
||||
addWarn("current funding fetch failed: " + err.Error())
|
||||
return nil
|
||||
}
|
||||
currentFund = f
|
||||
return nil
|
||||
})
|
||||
g.Go(func() error {
|
||||
oi, err := u.derivatives.GetCurrentOpenInterest(gctx, symbol)
|
||||
if err != nil {
|
||||
addWarn("current OI fetch failed: " + err.Error())
|
||||
return nil
|
||||
}
|
||||
currentOI = oi
|
||||
return nil
|
||||
})
|
||||
_ = g.Wait()
|
||||
|
||||
fundingHist, err := u.fundingRepo.FindRecent(ctx, symbol, derivativesFundingHistoryLen)
|
||||
if err != nil {
|
||||
addWarn("funding history query failed: " + err.Error())
|
||||
}
|
||||
|
||||
oiHist, err := u.oiRepo.FindRecent(ctx, symbol, period, derivativesOIHistoryLen)
|
||||
if err != nil {
|
||||
addWarn("OI history query failed: " + err.Error())
|
||||
}
|
||||
|
||||
globalLS, err := u.lsRepo.FindRecent(ctx, symbol, period, entity.RatioTypeGlobalAccount, derivativesLongShortLen)
|
||||
if err != nil {
|
||||
addWarn("global long/short query failed: " + err.Error())
|
||||
}
|
||||
|
||||
topLS, err := u.lsRepo.FindRecent(ctx, symbol, period, entity.RatioTypeTopTraderPosition, derivativesLongShortLen)
|
||||
if err != nil {
|
||||
addWarn("top trader position long/short query failed: " + err.Error())
|
||||
}
|
||||
|
||||
bundle := &entity.DerivativesBundle{
|
||||
Funding: entity.FundingBundle{
|
||||
Current: currentFund,
|
||||
History: fundingHist,
|
||||
},
|
||||
OpenInterest: entity.OpenInterestBundle{
|
||||
Current: currentOI,
|
||||
History: oiHist,
|
||||
},
|
||||
LongShortRatio: entity.LongShortBundle{
|
||||
Global: globalLS,
|
||||
TopTraderPosition: topLS,
|
||||
},
|
||||
TakerBuySellVolume: []entity.TakerBuySellVolume{},
|
||||
}
|
||||
|
||||
if warnings == nil {
|
||||
warnings = []string{}
|
||||
}
|
||||
return bundle, warnings, nil
|
||||
}
|
||||
Reference in New Issue
Block a user