package aside import ( "context" "sig-pub/api/pb" "sig-pub/pkg/data/entity" "sig-pub/pkg/mapping" "sig-pub/pkg/types" "sig-pub/pkg/utils/kvcache" "time" cache "github.com/fanjindong/go-cache" "golang.org/x/sync/singleflight" ) // TradeInstanceAside 交易实例客户端带缓存 // todo nats 更新监听 更新缓存 // grpc trade instance client type TradeInstanceAside struct { client pb.MarketClient cache *kvcache.KVCache[*entity.TradeInstance] cacheSf singleflight.Group } func NewTradeInstanceAside(client pb.MarketClient) *TradeInstanceAside { return &TradeInstanceAside{ client: client, cache: kvcache.NewExpireStore[*entity.TradeInstance]( time.Minute, cache.WithShards(16), cache.WithClearInterval(5*time.Minute), ), } } // GetTradeInstance 获取交易实例 // 高频访问,使用缓存 + singleflight func (c *TradeInstanceAside) GetTradeInstance(ctx context.Context, instId string) (inst *entity.TradeInstance, err error) { r, err, _ := c.cacheSf.Do(instId, func() (r any, err error) { return c.getTradeInstance0(ctx, instId) }) if err != nil { return } inst = r.(*entity.TradeInstance) return } func (c *TradeInstanceAside) getTradeInstance0(ctx context.Context, instId string) (inst *entity.TradeInstance, err error) { inst, ok := c.cache.Get(instId) if ok { return } // grpc 获取 rsp, err := c.client.GetTradeInstance(ctx, &pb.ReqGetTradeInstance{InstId: instId}) if err != nil { return } inst = mapping.Proto2TradeInstance(rsp.Inst) c.cache.Set(instId, inst) return } // ListExchangeTradeInstance 获取交易所支持的交易实例 func (c *TradeInstanceAside) ListExchangeTradeInstance(ctx context.Context, exchange types.Exchange) (exInsts []*entity.TradeInstanceExchange, err error) { pbExType, err := exchange.Exchange2PB() if err != nil { return } rsp, err := c.client.ListExchangeTradeInstance(ctx, &pb.ReqListExchangeTradeInstance{ Exchanges: []pb.Exchange{pbExType}, }) if err != nil { return } for _, pbExInst := range rsp.ExchangeInsts { exInst := mapping.Proto2ExchangeTradeInstance(pbExInst) exInsts = append(exInsts, exInst) } return }