package client import ( "context" "sig-pub/api/pb" "sig-pub/pkg/data/entity" "sig-pub/pkg/mapping" "sig-pub/pkg/utils/kvcache" "sig-pub/pkg/utils/retry" "sig-pub/pkg/zlog" "time" cache "github.com/fanjindong/go-cache" "golang.org/x/sync/singleflight" ) // TradeInstanceAside 交易实例客户端带缓存 // todo nats 更新监听 更新缓存 // grpc trade instance client type TradeInstanceAside struct { marketClient pb.MarketServiceClient cache *kvcache.KVCache[*entity.TradeInstance] cacheSf singleflight.Group } func NewTradeInstanceAside(marketClient pb.MarketServiceClient) *TradeInstanceAside { return &TradeInstanceAside{ marketClient: marketClient, 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.marketClient.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 pb.ExchangeType) (marketInsts []*pb.MarketTradeInstance, err error) { return retry.DoWithStepDelay(10, time.Second, func(retryTimes uint32) ([]*pb.MarketTradeInstance, error) { rsp, err := c.marketClient.ListMarketTradeInstance(ctx, &pb.ReqListMarketTradeInstance{Exchange: exchange}) if err != nil { zlog.Errorf("list market trade instances error: retry %d times, %v", retryTimes, err) return nil, err } return rsp.ExchangeInsts, nil }) }