fix: goroutine leak on shutdown, unsafe type assertions, redundant API calls

- Agent: add stopCh to cleanly stop chat-history-cleanup goroutine on Agent.Stop()
  (previously leaked a goroutine+ticker forever on every restart)
- Agent: add looksLikeStockQuery() guard to avoid hitting Sina search API on every
  single message — only calls external API when text contains stock-related content
  (saves ~200ms latency + API call on crypto-only queries)
- market/historical.go: safe type assertions in kline parsing (was bare .(float64)
  which panics on unexpected API responses), reuse HTTP client for connection pooling
- market/api_client.go: safe comma-ok type assertions for all kline field parsing
  (11 bare assertions → all guarded)
- trader/bybit: fix unsafe type assertion in CloseShort — pos["positionAmt"].(float64)
  could panic if field is nil/wrong type (critical: handles real money)
This commit is contained in:
shinchan-zhai
2026-03-23 19:20:04 +08:00
parent efdf4856c5
commit 1f8493c0cf
4 changed files with 144 additions and 35 deletions

View File

@@ -30,7 +30,14 @@ func GetKlinesRange(symbol string, timeframe string, start, end time.Time) ([]Kl
var all []Kline
cursor := startMs
client := &http.Client{Timeout: 15 * time.Second}
client := &http.Client{
Timeout: 15 * time.Second,
Transport: &http.Transport{
MaxIdleConns: 5,
MaxIdleConnsPerHost: 5,
IdleConnTimeout: 90 * time.Second,
},
}
for cursor < endMs {
req, err := http.NewRequest("GET", binanceFuturesKlinesURL, nil)
@@ -68,25 +75,37 @@ func GetKlinesRange(symbol string, timeframe string, start, end time.Time) ([]Kl
break
}
batch := make([]Kline, len(raw))
for i, item := range raw {
openTime := int64(item[0].(float64))
batch := make([]Kline, 0, len(raw))
for _, item := range raw {
if len(item) < 7 {
continue // skip malformed entries
}
openTimeF, ok := item[0].(float64)
if !ok {
continue
}
closeTimeF, ok := item[6].(float64)
if !ok {
continue
}
open, _ := parseFloat(item[1])
high, _ := parseFloat(item[2])
low, _ := parseFloat(item[3])
close, _ := parseFloat(item[4])
cls, _ := parseFloat(item[4])
volume, _ := parseFloat(item[5])
closeTime := int64(item[6].(float64))
batch[i] = Kline{
OpenTime: openTime,
batch = append(batch, Kline{
OpenTime: int64(openTimeF),
Open: open,
High: high,
Low: low,
Close: close,
Close: cls,
Volume: volume,
CloseTime: closeTime,
}
CloseTime: int64(closeTimeF),
})
}
if len(batch) == 0 {
break
}
all = append(all, batch...)