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.
 
 

144 lines
4.0 KiB

package exchange
import (
"context"
"fmt"
"io"
"sig-pub/api/pb"
"sig-pub/pkg/zlog"
"sync/atomic"
"google.golang.org/grpc"
)
type ExchangeGrpcServer struct {
pb.UnimplementedExchangeServiceServer
exchangeService *ExchangeService
klineStreamId int64
klineSubscriber *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) {
rsp = &pb.RspHistoryKline{
Exchange: req.Exchange,
InstId: req.InstId,
Interval: req.Interval,
}
// for before := req.Before; ; {
// }
klines, err := svr.exchangeService.HistoryKline(ctx, req, rsp)
if err != nil {
return
}
rsp.Klines = make([]*pb.Kline, 0, len(klines))
for _, k := range klines {
rsp.Klines = append(rsp.Klines, k.ToPBKline())
}
return
}
// HistoryKlineStream 获取交易产品历史k线(流式返回)
func (svr *ExchangeGrpcServer) HistoryKlineStream(req *pb.ReqHistoryKlineStream, stream grpc.ServerStreamingServer[pb.RspHistoryKlineStream]) (err error) {
err = svr.exchangeService.HistoryKlineStream(req, stream)
return
}