blockchain/internal/logic/blockchainservice/get_history_kline_data_logi...

108 lines
2.7 KiB
Go
Raw Normal View History

2025-08-14 23:41:29 +00:00
package blockchainservicelogic
import (
"blockchain/internal/domain/usecase"
"context"
2025-08-20 09:34:27 +00:00
"fmt"
2025-08-14 23:41:29 +00:00
"time"
"blockchain/gen_result/pb/code.30cm.net/digimon/app-cloudep-blockchain"
"blockchain/internal/svc"
"github.com/zeromicro/go-zero/core/logx"
)
type GetHistoryKlineDataLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewGetHistoryKlineDataLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetHistoryKlineDataLogic {
return &GetHistoryKlineDataLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
func (l *GetHistoryKlineDataLogic) GetHistoryKlineData(in *app_cloudep_blockchain.HistoryReq) (*app_cloudep_blockchain.OKResp, error) {
2025-08-20 09:34:27 +00:00
// 1) 先驗證輸入(避免把錯誤時間丟進背景 goroutine
st, err := time.Parse(time.RFC3339, in.GetStartTime())
if err != nil {
return nil, fmt.Errorf("invalid startTime (RFC3339): %w", err)
}
et, err := time.Parse(time.RFC3339, in.GetEndTime())
if err != nil {
return nil, fmt.Errorf("invalid endTime (RFC3339): %w", err)
}
if !st.Before(et) {
return nil, fmt.Errorf("startTime must be before endTime")
}
chunks := splitByWeeksUTC(st, et)
if len(chunks) == 0 {
return &app_cloudep_blockchain.OKResp{}, nil
}
for _, ch := range chunks {
timeBucket := ch
err := l.svcCtx.WorkerPools.Submit(func() {
_ = l.svcCtx.BinanceDataSource.UpsertKline(context.Background(), usecase.QueryKline{
Symbol: in.GetSymbol(),
Interval: in.GetInterval(),
StartTime: timeBucket.start.UnixNano(),
EndTime: timeBucket.end.UnixNano(),
})
2025-08-14 23:41:29 +00:00
})
2025-08-20 09:34:27 +00:00
if err != nil {
return nil, err
}
}
2025-08-14 23:41:29 +00:00
return &app_cloudep_blockchain.OKResp{}, nil
}
2025-08-20 09:34:27 +00:00
// --------- 小工具按「週一起」切段UTC ---------
type timeRange struct {
start time.Time // 含
end time.Time // 不含
}
// 取得該時間所在「週一 00:00:00」(UTC)
func weekStartMondayUTC(t time.Time) time.Time {
t = t.UTC()
// Go: Sunday=0 ... Saturday=6我們要週一=起始
wd := int(t.Weekday())
if wd == 0 { // Sunday
wd = 7
}
// 將時間歸零到當天 00:00
d0 := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.UTC)
// 回推到週一
return d0.AddDate(0, 0, -(wd - 1))
}
// 將 [start,end) 切成多個「週粒度」的區間
func splitByWeeksUTC(start, end time.Time) []timeRange {
var chunks []timeRange
if !start.Before(end) {
return chunks
}
cur := start.UTC()
end = end.UTC()
for cur.Before(end) {
// 下一個週一 00:00
nextWeekStart := weekStartMondayUTC(cur).AddDate(0, 0, 7)
chunkEnd := end
if nextWeekStart.Before(end) {
chunkEnd = nextWeekStart
}
chunks = append(chunks, timeRange{start: cur, end: chunkEnd})
cur = chunkEnd
}
return chunks
}