|
|
|
@ -6,7 +6,8 @@ import ( |
|
|
|
"io" |
|
|
|
"io" |
|
|
|
"sig-pub/api/pb" |
|
|
|
"sig-pub/api/pb" |
|
|
|
"sig-pub/pkg/aside" |
|
|
|
"sig-pub/pkg/aside" |
|
|
|
"sig-pub/pkg/data/entity" |
|
|
|
"sig-pub/pkg/data" |
|
|
|
|
|
|
|
"sig-pub/pkg/storage/kvrocks" |
|
|
|
"sig-pub/pkg/types" |
|
|
|
"sig-pub/pkg/types" |
|
|
|
"sig-pub/pkg/zlog" |
|
|
|
"sig-pub/pkg/zlog" |
|
|
|
"sync" |
|
|
|
"sync" |
|
|
|
@ -15,43 +16,34 @@ import ( |
|
|
|
"google.golang.org/grpc" |
|
|
|
"google.golang.org/grpc" |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
type Exchange struct { |
|
|
|
|
|
|
|
Type pb.Exchange |
|
|
|
|
|
|
|
Subscriber ExchangeSubscriber |
|
|
|
|
|
|
|
Insts map[string]*entity.TradeInstanceExchange |
|
|
|
|
|
|
|
sync.RWMutex |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type ExchangeGrpcServer struct { |
|
|
|
type ExchangeGrpcServer struct { |
|
|
|
pb.UnimplementedExchangeServiceServer |
|
|
|
pb.UnimplementedExchangeServiceServer |
|
|
|
exchangeMap map[pb.Exchange]*Exchange |
|
|
|
exchangeMap map[types.Exchange]*Exchange |
|
|
|
tradeInstanceAside *aside.TradeInstanceAside |
|
|
|
tradeInstanceAside *aside.TradeInstanceAside |
|
|
|
exchangeDataService *ExchangeDataService |
|
|
|
exchangeDataService *ExchangeDataService |
|
|
|
|
|
|
|
kvdb *kvrocks.KVRocksDB |
|
|
|
|
|
|
|
|
|
|
|
klineStreamId int64 |
|
|
|
klineStreamId int64 |
|
|
|
klinePublisher *Publisher[int64, grpc.BidiStreamingServer[pb.ReqStreamSubscribeKline, pb.RspStreamSubscribeKline]] |
|
|
|
klinePublisher *Publisher[int64, grpc.BidiStreamingServer[pb.ReqStreamSubscribeKline, pb.RspStreamSubscribeKline]] |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// exchanges: 支持的数据源交易所
|
|
|
|
// exchanges: 支持的数据源交易所
|
|
|
|
func NewExchangeGrpcServer(tradeInstanceAside *aside.TradeInstanceAside, exchangeDataService *ExchangeDataService, exchanges ...ExchangeSubscriber) *ExchangeGrpcServer { |
|
|
|
func NewExchangeGrpcServer( |
|
|
|
exchangeMap := make(map[pb.Exchange]*Exchange) |
|
|
|
tradeInstanceAside *aside.TradeInstanceAside, |
|
|
|
|
|
|
|
exchangeDataService *ExchangeDataService, |
|
|
|
|
|
|
|
kvdb *kvrocks.KVRocksDB, |
|
|
|
|
|
|
|
exchanges ...*Exchange, |
|
|
|
|
|
|
|
) *ExchangeGrpcServer { |
|
|
|
|
|
|
|
exchangeMap := make(map[types.Exchange]*Exchange) |
|
|
|
for _, exchange := range exchanges { |
|
|
|
for _, exchange := range exchanges { |
|
|
|
exchangeType := exchange.ExhcangeType() |
|
|
|
exchangeMap[exchange.ExType] = exchange |
|
|
|
pbExchangeType, ok := exchangeType.Exchange2PB() |
|
|
|
|
|
|
|
if !ok { |
|
|
|
|
|
|
|
panic(fmt.Errorf("unknown exchange: %#v", exchangeType)) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
exchangeMap[pbExchangeType] = &Exchange{ |
|
|
|
|
|
|
|
Type: pbExchangeType, |
|
|
|
|
|
|
|
Subscriber: exchange, |
|
|
|
|
|
|
|
Insts: make(map[string]*entity.TradeInstanceExchange), |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return &ExchangeGrpcServer{ |
|
|
|
return &ExchangeGrpcServer{ |
|
|
|
exchangeMap: exchangeMap, |
|
|
|
exchangeMap: exchangeMap, |
|
|
|
tradeInstanceAside: tradeInstanceAside, |
|
|
|
tradeInstanceAside: tradeInstanceAside, |
|
|
|
exchangeDataService: exchangeDataService, |
|
|
|
exchangeDataService: exchangeDataService, |
|
|
|
|
|
|
|
kvdb: kvdb, |
|
|
|
klinePublisher: NewPublisher[int64, grpc.BidiStreamingServer[pb.ReqStreamSubscribeKline, pb.RspStreamSubscribeKline]](16), |
|
|
|
klinePublisher: NewPublisher[int64, grpc.BidiStreamingServer[pb.ReqStreamSubscribeKline, pb.RspStreamSubscribeKline]](16), |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -68,16 +60,30 @@ func (svc *ExchangeGrpcServer) subscribeExchanges() { |
|
|
|
for _, exchange := range svc.exchangeMap { |
|
|
|
for _, exchange := range svc.exchangeMap { |
|
|
|
go func(exchange *Exchange) { |
|
|
|
go func(exchange *Exchange) { |
|
|
|
// get exchange trade instances
|
|
|
|
// get exchange trade instances
|
|
|
|
insts, err := svc.tradeInstanceAside.ListExchangeTradeInstance(context.Background(), exchange.Type) |
|
|
|
insts, err := svc.tradeInstanceAside.ListExchangeTradeInstance(context.Background(), exchange.ExType) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
zlog.Error(err) |
|
|
|
zlog.Error(err) |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var exchangeInstIds []string |
|
|
|
var exchangeInstIds []string |
|
|
|
|
|
|
|
var processingInsts []types.TradeInstance |
|
|
|
exchange.Lock() |
|
|
|
exchange.Lock() |
|
|
|
for _, inst := range insts { |
|
|
|
for _, inst := range insts { |
|
|
|
exchangeInstIds = append(exchangeInstIds, inst.ExchangeInstId) |
|
|
|
exchangeInstIds = append(exchangeInstIds, inst.ExchangeInstId) |
|
|
|
exchange.Insts[inst.ExchangeInstId] = inst |
|
|
|
tradeInst := &types.TradeInstance{ |
|
|
|
|
|
|
|
InstId: inst.InstId, |
|
|
|
|
|
|
|
Status: inst.Status, |
|
|
|
|
|
|
|
PriceSz: 0, |
|
|
|
|
|
|
|
QuantitySz: 0, |
|
|
|
|
|
|
|
ExchangeInstId: inst.ExchangeInstId, |
|
|
|
|
|
|
|
Exchange: exchange.ExType, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
exchange.Insts[inst.ExchangeInstId] = tradeInst |
|
|
|
|
|
|
|
// 待初始化币种数据
|
|
|
|
|
|
|
|
if inst.Status == data.StatusProcessing { |
|
|
|
|
|
|
|
processingInsts = append(processingInsts, *tradeInst) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
exchange.Unlock() |
|
|
|
exchange.Unlock() |
|
|
|
|
|
|
|
|
|
|
|
@ -87,20 +93,23 @@ func (svc *ExchangeGrpcServer) subscribeExchanges() { |
|
|
|
zlog.Error(err) |
|
|
|
zlog.Error(err) |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
go func() { |
|
|
|
c := exchange.Subscriber.ConsumerKline() |
|
|
|
c := exchange.Subscriber.ConsumerKline() |
|
|
|
svc.consumerKline(exchange, c) |
|
|
|
svc.consumerKline(exchange, c) |
|
|
|
// todo subscribe books 订单簿
|
|
|
|
// todo subscribe books 订单簿
|
|
|
|
zlog.Infof("unsubscribe exchange: %s", exchange.Type.String()) |
|
|
|
zlog.Infof("unsubscribe exchange: %s", exchange.ExType) |
|
|
|
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化k线数据
|
|
|
|
|
|
|
|
go svc.initialKlines(exchange, processingInsts) |
|
|
|
}(exchange) |
|
|
|
}(exchange) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// consumerKline 消费交易所k线数据
|
|
|
|
// consumerKline 消费交易所k线数据
|
|
|
|
func (svc *ExchangeGrpcServer) consumerKline(exchange *Exchange, c <-chan *types.ChannelKline) { |
|
|
|
func (svc *ExchangeGrpcServer) consumerKline(exchange *Exchange, c <-chan *types.ChannelKline) { |
|
|
|
exchangeType, ok := types.ExchangePBParse(exchange.Type) |
|
|
|
exchangeType := exchange.ExType |
|
|
|
if !ok { |
|
|
|
|
|
|
|
panic(fmt.Errorf("unknown exchange type: %v", exchange.Type)) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for { |
|
|
|
for { |
|
|
|
channelK, ok := <-c |
|
|
|
channelK, ok := <-c |
|
|
|
@ -109,7 +118,7 @@ func (svc *ExchangeGrpcServer) consumerKline(exchange *Exchange, c <-chan *types |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 交易所 instid 转 sig-instid
|
|
|
|
// 交易所 instid 转 sig-instid
|
|
|
|
var exInst *entity.TradeInstanceExchange |
|
|
|
var exInst *types.TradeInstance |
|
|
|
exchange.RLock() |
|
|
|
exchange.RLock() |
|
|
|
if inst, ok := exchange.Insts[channelK.InstId]; ok && inst != nil { |
|
|
|
if inst, ok := exchange.Insts[channelK.InstId]; ok && inst != nil { |
|
|
|
exchange.RUnlock() |
|
|
|
exchange.RUnlock() |
|
|
|
@ -124,12 +133,11 @@ func (svc *ExchangeGrpcServer) consumerKline(exchange *Exchange, c <-chan *types |
|
|
|
pubMsgMap := make(map[string]*pb.StreamKline) |
|
|
|
pubMsgMap := make(map[string]*pb.StreamKline) |
|
|
|
|
|
|
|
|
|
|
|
// instId := channelK.InstId
|
|
|
|
// instId := channelK.InstId
|
|
|
|
exchange, ok := channelK.Exchange.Exchange2PB() |
|
|
|
pbExType, err := channelK.Exchange.Exchange2PB() |
|
|
|
if !ok { |
|
|
|
if err != nil { |
|
|
|
zlog.Errorf("unknown exchange kline: %v", channelK.Exchange) |
|
|
|
zlog.Error(err) |
|
|
|
continue |
|
|
|
continue |
|
|
|
} |
|
|
|
} |
|
|
|
exchangeName := exchange.String() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var confirmKlines []*types.Kline |
|
|
|
var confirmKlines []*types.Kline |
|
|
|
for _, kline := range channelK.Klines { |
|
|
|
for _, kline := range channelK.Klines { |
|
|
|
@ -139,13 +147,13 @@ func (svc *ExchangeGrpcServer) consumerKline(exchange *Exchange, c <-chan *types |
|
|
|
confirm = 1 |
|
|
|
confirm = 1 |
|
|
|
confirmKlines = append(confirmKlines, kline) |
|
|
|
confirmKlines = append(confirmKlines, kline) |
|
|
|
} |
|
|
|
} |
|
|
|
pubKey := fmt.Sprintf("/kline/%s/%s/%s/%d", exchangeName, exInst.InstId, kline.Interval, confirm) |
|
|
|
pubKey := fmt.Sprintf("/kline/%s/%s/%s/%d", exchangeType, exInst.InstId, kline.Interval, confirm) |
|
|
|
// todo 优化没有订阅者就跳过
|
|
|
|
// todo 优化没有订阅者就跳过
|
|
|
|
msg, ok := pubMsgMap[pubKey] |
|
|
|
msg, ok := pubMsgMap[pubKey] |
|
|
|
if !ok { |
|
|
|
if !ok { |
|
|
|
msg = new(pb.StreamKline) |
|
|
|
msg = new(pb.StreamKline) |
|
|
|
msg.InstId = exInst.InstId |
|
|
|
msg.InstId = exInst.InstId |
|
|
|
msg.Exchange = exchange |
|
|
|
msg.Exchange = pbExType |
|
|
|
pubMsgMap[pubKey] = msg |
|
|
|
pubMsgMap[pubKey] = msg |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -155,14 +163,8 @@ func (svc *ExchangeGrpcServer) consumerKline(exchange *Exchange, c <-chan *types |
|
|
|
|
|
|
|
|
|
|
|
// tsdb storage
|
|
|
|
// tsdb storage
|
|
|
|
if len(confirmKlines) > 0 { |
|
|
|
if len(confirmKlines) > 0 { |
|
|
|
typeInst := types.TradeInstance{ |
|
|
|
|
|
|
|
InstId: exInst.InstId, // channelK.InstId
|
|
|
|
|
|
|
|
PriceSz: 0, |
|
|
|
|
|
|
|
QuantitySz: 0, |
|
|
|
|
|
|
|
Exchange: exchangeType, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// todo 异步处理
|
|
|
|
// todo 异步处理
|
|
|
|
err := svc.exchangeDataService.SaveKlines(typeInst, confirmKlines) |
|
|
|
err := svc.exchangeDataService.SaveKlines(*exInst, confirmKlines) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
zlog.Errorf("kline save to tsdb error: ", err) |
|
|
|
zlog.Errorf("kline save to tsdb error: ", err) |
|
|
|
} |
|
|
|
} |
|
|
|
@ -279,3 +281,161 @@ func (svc *ExchangeGrpcServer) SubscribeKline(stream grpc.BidiStreamingServer[pb |
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const ( |
|
|
|
|
|
|
|
KlineBefore0 int64 = 1672502400000 // k线开始数据 2023-01-01 00:00:00 GMT+8
|
|
|
|
|
|
|
|
HistoryKlineTsKey string = "history-kline-ts:%s/%s/%s" // exchange:sig-instid:interval
|
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// initialKline 初始化交易产品历史k线数据
|
|
|
|
|
|
|
|
func (svc *ExchangeGrpcServer) initialKlines(exchange *Exchange, insts []types.TradeInstance) { |
|
|
|
|
|
|
|
var err error |
|
|
|
|
|
|
|
defer func() { |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
zlog.Error(err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type task struct { |
|
|
|
|
|
|
|
inst types.TradeInstance |
|
|
|
|
|
|
|
interval types.Interval |
|
|
|
|
|
|
|
afterTs int64 |
|
|
|
|
|
|
|
beforeTs int64 |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 任务 channel
|
|
|
|
|
|
|
|
ch := make(chan task) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 任务生成器
|
|
|
|
|
|
|
|
go func() { |
|
|
|
|
|
|
|
for _, inst := range insts { |
|
|
|
|
|
|
|
// for interval, intervalAdder := range types.SupportedIntervals {
|
|
|
|
|
|
|
|
interval := types.Interval1h |
|
|
|
|
|
|
|
intervalAdder := types.SupportedIntervals[interval] |
|
|
|
|
|
|
|
tsKey := fmt.Sprintf(HistoryKlineTsKey, inst.Exchange, inst.InstId, interval) |
|
|
|
|
|
|
|
beforeTs, e := svc.kvdb.GetI64(context.Background(), tsKey) |
|
|
|
|
|
|
|
if e != nil { |
|
|
|
|
|
|
|
err = e |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if beforeTs == 0 { |
|
|
|
|
|
|
|
beforeTs = intervalAdder(KlineBefore0, -1) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
for { |
|
|
|
|
|
|
|
afterTs := intervalAdder(beforeTs, 101) |
|
|
|
|
|
|
|
ch <- task{ |
|
|
|
|
|
|
|
inst: inst, |
|
|
|
|
|
|
|
interval: interval, |
|
|
|
|
|
|
|
afterTs: afterTs, |
|
|
|
|
|
|
|
beforeTs: beforeTs, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
beforeTs = afterTs |
|
|
|
|
|
|
|
// todo compare ws live ts
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
close(ch) |
|
|
|
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 任务消费器 8协程并行
|
|
|
|
|
|
|
|
wg := new(sync.WaitGroup) |
|
|
|
|
|
|
|
for range 11 { |
|
|
|
|
|
|
|
wg.Add(1) |
|
|
|
|
|
|
|
go func() { |
|
|
|
|
|
|
|
defer wg.Done() |
|
|
|
|
|
|
|
for { |
|
|
|
|
|
|
|
task, ok := <-ch |
|
|
|
|
|
|
|
if !ok { |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
interval, afterTs, beforeTs := task.interval, task.afterTs, task.beforeTs |
|
|
|
|
|
|
|
klines, e := exchange.Fetcher.FetchHistoryKlines(context.Background(), task.inst.ExchangeInstId, interval, afterTs, beforeTs) |
|
|
|
|
|
|
|
if e != nil { |
|
|
|
|
|
|
|
// todo retry
|
|
|
|
|
|
|
|
err = e |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if len(klines) == 0 { |
|
|
|
|
|
|
|
continue // todo ....
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
zlog.Infof("fetch interval %s %d~%d klines: ret=%d~%d, %d klines", interval, afterTs, beforeTs, klines[0].Ts, klines[len(klines)-1].Ts, len(klines)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// store to tsdb
|
|
|
|
|
|
|
|
err = svc.exchangeDataService.SaveKlines(task.inst, klines) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
wg.Wait() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
zlog.Infof("%d insts initial finished", len(insts)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// var intervals []types.Interval
|
|
|
|
|
|
|
|
// for interval := range types.SupportedIntervals {
|
|
|
|
|
|
|
|
// intervals = append(intervals, interval)
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// var intervalsTs = make([]int, len(intervals))
|
|
|
|
|
|
|
|
// var index int
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// var lock sync.Mutex
|
|
|
|
|
|
|
|
// var getTask = func() (interval types.Interval, afterTs, beforeTs int64) {
|
|
|
|
|
|
|
|
// lock.Lock()
|
|
|
|
|
|
|
|
// ts := intervalsTs[index]
|
|
|
|
|
|
|
|
// if ts == -1 {
|
|
|
|
|
|
|
|
// index++
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// lock.Unlock()
|
|
|
|
|
|
|
|
// return
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// var finishTask = func(interval types.Interval) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ctx := context.Background()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// inst := insts[0]
|
|
|
|
|
|
|
|
// // for interval, intervalAdder := range types.SupportedIntervals {
|
|
|
|
|
|
|
|
// interval := types.Interval1h
|
|
|
|
|
|
|
|
// intervalAdder := types.SupportedIntervals[interval]
|
|
|
|
|
|
|
|
// // kvrocks get exchange+inst+interval last/ts
|
|
|
|
|
|
|
|
// tsKey := fmt.Sprintf(HistoryKlineTsKey, inst.Exchange, inst.InstId, interval)
|
|
|
|
|
|
|
|
// beforeTs, e := svc.kvdb.GetI64(ctx, tsKey)
|
|
|
|
|
|
|
|
// if e != nil {
|
|
|
|
|
|
|
|
// err = e
|
|
|
|
|
|
|
|
// return
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// if beforeTs == 0 {
|
|
|
|
|
|
|
|
// beforeTs = intervalAdder(KlineBefore0, -1)
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// for {
|
|
|
|
|
|
|
|
// afterTs := intervalAdder(beforeTs, 101)
|
|
|
|
|
|
|
|
// klines, e := exchange.Fetcher.FetchHistoryKlines(ctx, inst.ExchangeInstId, interval, afterTs, beforeTs)
|
|
|
|
|
|
|
|
// if e != nil {
|
|
|
|
|
|
|
|
// err = e
|
|
|
|
|
|
|
|
// return
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// if len(klines) == 0 {
|
|
|
|
|
|
|
|
// break
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// zlog.Infof("fetch interval %s %d~%d klines: ret=%d~%d, %d klines", interval, afterTs, beforeTs, klines[0].Ts, klines[len(klines)-1].Ts, len(klines))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // store to tsdb
|
|
|
|
|
|
|
|
// err = svc.exchangeDataService.SaveKlines(inst, klines)
|
|
|
|
|
|
|
|
// if err != nil {
|
|
|
|
|
|
|
|
// return
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // set kvdb inst ts mark
|
|
|
|
|
|
|
|
// beforeTs = klines[0].Ts
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// zlog.Infof("%s %s initial finished", inst.Exchange, inst.InstId)
|
|
|
|
|
|
|
|
} |
|
|
|
|