You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
168 lines
4.7 KiB
168 lines
4.7 KiB
package exchange |
|
|
|
import ( |
|
"context" |
|
"fmt" |
|
"io" |
|
"sig-pub/api/pb" |
|
"sig-pub/pkg/publish" |
|
"sig-pub/pkg/zlog" |
|
"sync/atomic" |
|
|
|
"google.golang.org/grpc" |
|
) |
|
|
|
type ExchangeGrpcServer struct { |
|
pb.UnimplementedExchangeServiceServer |
|
exchangeService *ExchangeService |
|
klineStreamId int64 |
|
|
|
klineSubscriber *publish.Publisher[int64, grpc.BidiStreamingServer[pb.ReqStreamSubscribeKline, pb.RspStreamSubscribeKline]] |
|
} |
|
|
|
// exchanges: 支持的数据源交易所 |
|
func NewExchangeGrpcServer(exchangeService *ExchangeService) *ExchangeGrpcServer { |
|
return &ExchangeGrpcServer{ |
|
exchangeService: exchangeService, |
|
} |
|
} |
|
|
|
func (svr *ExchangeGrpcServer) Init() (err error) { |
|
svr.klineSubscriber = svr.exchangeService.GetKlineSubscriber() |
|
return |
|
} |
|
|
|
// SubscribeKline 订阅k线stream |
|
func (svr *ExchangeGrpcServer) SubscribeKline(stream grpc.BidiStreamingServer[pb.ReqStreamSubscribeKline, pb.RspStreamSubscribeKline]) (err0 error) { |
|
streamId := atomic.AddInt64(&svr.klineStreamId, 1) |
|
// subKey = /kline/exchange/instId/interval/confirm -> /kline/OKX/DOGE-USDT-SWAP/1s/1 |
|
|
|
// 接收消息的goroutine |
|
recvChan := make(chan *pb.ReqStreamSubscribeKline) |
|
go func() { |
|
for { |
|
msg, err := stream.Recv() |
|
if err == io.EOF { |
|
zlog.Infof("recv close EOF") |
|
close(recvChan) |
|
return |
|
} |
|
if err != nil { |
|
zlog.Infof("recv error: %v", err) |
|
close(recvChan) |
|
return |
|
} |
|
zlog.Infof("recv stream msg: %#v", msg) |
|
recvChan <- msg |
|
} |
|
}() |
|
|
|
// 发送和处理消息 |
|
for { |
|
select { |
|
case <-stream.Context().Done(): |
|
// 客户端断开连接 |
|
svr.klineSubscriber.UnsubscribeAll(streamId) |
|
return stream.Context().Err() |
|
case msg, ok := <-recvChan: |
|
if !ok { |
|
// 接收通道关闭,结束流 |
|
svr.klineSubscriber.UnsubscribeAll(streamId) |
|
return |
|
} |
|
|
|
if msg.SubType == pb.SubscribeType_UnsubscribeAll { |
|
svr.klineSubscriber.UnsubscribeAll(streamId) |
|
continue |
|
} |
|
for _, exchange := range msg.Exchanges { |
|
for _, instId := range msg.InstIds { |
|
for _, interval := range msg.Intervals { |
|
confirms := []int{1} |
|
if !msg.OnlyConfirm { |
|
confirms = append(confirms, 0) |
|
} |
|
for _, confirm := range confirms { |
|
subKey := fmt.Sprintf("/kline/%s/%s/%s/%d", exchange.String(), instId, interval, confirm) |
|
zlog.Debugf("stream: id=%d, sub %s", streamId, subKey) |
|
switch msg.SubType { |
|
case pb.SubscribeType_Subscribe: |
|
svr.klineSubscriber.Subscribe(subKey, streamId, stream) |
|
case pb.SubscribeType_Unsubscribe: |
|
svr.klineSubscriber.Unsubscribe(subKey, streamId) |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
// Exchanges 获取支持的交易所列表 |
|
func (svr *ExchangeGrpcServer) Exchanges(ctx context.Context, req *pb.ReqExchanges) (rsp *pb.RspExchanges, err error) { |
|
exchanges, err := svr.exchangeService.Exchanges() |
|
if err != nil { |
|
return |
|
} |
|
return &pb.RspExchanges{Exchanges: exchanges}, nil |
|
} |
|
|
|
// ExchangeInstanceState 获取交易产品系统状态 |
|
func (svr *ExchangeGrpcServer) ExchangeInstanceState(ctx context.Context, req *pb.ReqExchangeInstanceState) (rsp *pb.RspExchangeInstanceState, err error) { |
|
states, err := svr.exchangeService.ExchangeInstanceState(req) |
|
if err != nil { |
|
return |
|
} |
|
return &pb.RspExchangeInstanceState{InstsState: states}, nil |
|
} |
|
|
|
// HistoryKline 获取交易产品历史k线 (before < klines... < after) |
|
func (svr *ExchangeGrpcServer) HistoryKline(ctx context.Context, req *pb.ReqHistoryKline) (rsp *pb.RspHistoryKline, err error) { |
|
if req.Series == nil { |
|
err = fmt.Errorf("series arg is required") |
|
return |
|
} |
|
// 查询范围数据条数检查 |
|
_, _, total, err := svr.exchangeService.CalcSeriesRange(req.Series) |
|
if err != nil { |
|
return |
|
} |
|
if total > DefaultHistoryKlines { |
|
err = fmt.Errorf("time range too large max %d", DefaultHistoryKlines) |
|
return |
|
} |
|
|
|
rsp = new(pb.RspHistoryKline) |
|
rsp.Klines = make([]*pb.Kline, 0, total+1) |
|
rsp = &pb.RspHistoryKline{ |
|
Exchange: req.Series.Exchange, |
|
InstId: req.Series.InstId, |
|
Interval: req.Series.Interval, |
|
} |
|
live, err := svr.exchangeService.HistoryKline(req.Series, DefaultHistoryKlines, func(klines []*pb.Kline) error { |
|
rsp.Klines = append(rsp.Klines, klines...) |
|
return nil |
|
}) |
|
if err != nil { |
|
return |
|
} |
|
rsp.Live = live |
|
return |
|
} |
|
|
|
// HistoryKlineStream 获取交易产品历史k线(流式返回) |
|
func (svr *ExchangeGrpcServer) HistoryKlineStream(req *pb.ReqHistoryKlineStream, stream grpc.ServerStreamingServer[pb.RspHistoryKlineStream]) (err error) { |
|
if req.Series == nil { |
|
err = fmt.Errorf("series arg is required") |
|
return |
|
} |
|
_, err = svr.exchangeService.HistoryKline(req.Series, 200, func(klines []*pb.Kline) error { |
|
rsp := &pb.RspHistoryKlineStream{Klines: klines} |
|
return stream.Send(rsp) |
|
}) |
|
if err != nil { |
|
return |
|
} |
|
return |
|
}
|
|
|