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.AllExchange, req.Exchanges, req.Insts) 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 }