123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- package usersuit
- import (
- "context"
- "sync"
- "time"
- "go-common/app/interface/main/account/model"
- accmdl "go-common/app/service/main/account/model"
- usmdl "go-common/app/service/main/usersuit/model"
- "go-common/library/log"
- "go-common/library/net/metadata"
- "go-common/library/sync/errgroup"
- )
- const (
- _batch = 20
- _fetchInfoTimeout = time.Second * 10
- )
- var (
- _emptyRichInvites = make([]*model.RichInvite, 0)
- _emptyInfoMap = make(map[int64]*accmdl.Info)
- )
- // Buy buy invite code.
- func (s *Service) Buy(c context.Context, mid int64, num int64) (res []*model.RichInvite, err error) {
- var invs []*usmdl.Invite
- ip := metadata.String(c, metadata.RemoteIP)
- arg := &usmdl.ArgBuy{Mid: mid, Num: num, IP: ip}
- if invs, err = s.usRPC.Buy(c, arg); err != nil {
- log.Error("service.userserviceRPC.Buy(%v) error(%v)", arg, err)
- return
- }
- res = make([]*model.RichInvite, 0)
- for _, inv := range invs {
- res = append(res, model.NewRichInvite(inv, nil))
- }
- return
- }
- // Apply apply invite code.
- func (s *Service) Apply(c context.Context, mid int64, code string, cookie string) (err error) {
- ip := metadata.String(c, metadata.RemoteIP)
- arg := &usmdl.ArgApply{Mid: mid, Code: code, Cookie: cookie, IP: ip}
- if err = s.usRPC.Apply(c, arg); err != nil {
- log.Error("service.userserviceRPC.Apply(%v) error(%v)", arg, err)
- }
- return
- }
- // Stat get user's invite code stat.
- func (s *Service) Stat(c context.Context, mid int64) (res *model.RichInviteStat, err error) {
- var st *usmdl.InviteStat
- ip := metadata.String(c, metadata.RemoteIP)
- arg := &usmdl.ArgStat{Mid: mid, IP: ip}
- if st, err = s.usRPC.Stat(c, arg); err != nil {
- log.Error("service.userserviceRPC.Stat(%v) error(%v)", arg, err)
- return
- }
- res = &model.RichInviteStat{
- Mid: st.Mid,
- CurrentLimit: st.CurrentLimit,
- CurrentBought: st.CurrentBought,
- TotalBought: st.TotalBought,
- TotalUsed: st.TotalUsed,
- InviteCodes: s.fillInviteeInfo(c, st.InviteCodes, ip),
- }
- return
- }
- func (s *Service) fillInviteeInfo(c context.Context, invs []*usmdl.Invite, ip string) []*model.RichInvite {
- if len(invs) == 0 {
- return _emptyRichInvites
- }
- imidm := make(map[int64]int)
- for _, inv := range invs {
- if inv.Status == usmdl.StatusUsed {
- imidm[inv.Imid] = 1
- }
- }
- infom := _emptyInfoMap
- if len(imidm) > 0 {
- imids := make([]int64, 0, len(imidm))
- for imid := range imidm {
- imids = append(imids, imid)
- }
- var err1 error
- if infom, err1 = s.fetchInfos(c, imids, ip, _fetchInfoTimeout); err1 != nil {
- log.Error("service.fetchInfos(%v, %s, %v) error(%v)", imids, ip, _fetchInfoTimeout, err1)
- }
- }
- rinvs := make([]*model.RichInvite, 0)
- for _, inv := range invs {
- rinvs = append(rinvs, model.NewRichInvite(inv, infom[inv.Imid]))
- }
- return rinvs
- }
- func (s *Service) fetchInfos(c context.Context, mids []int64, ip string, timeout time.Duration) (res map[int64]*accmdl.Info, err error) {
- if len(mids) == 0 {
- res = _emptyInfoMap
- return
- }
- batches := len(mids)/_batch + 1
- tc, cancel := context.WithTimeout(c, timeout)
- defer cancel()
- eg, errCtx := errgroup.WithContext(tc)
- bms := make([]map[int64]*accmdl.Info, batches)
- mu := sync.Mutex{}
- for i := 0; i < batches; i++ {
- idx := i
- end := (idx + 1) * _batch
- if idx == batches-1 {
- end = len(mids)
- }
- ids := mids[idx*_batch : end]
- eg.Go(func() error {
- m, err1 := s.accRPC.Infos3(errCtx, &accmdl.ArgMids{Mids: ids})
- mu.Lock()
- bms[idx] = m
- mu.Unlock()
- return err1
- })
- }
- err = eg.Wait()
- res = make(map[int64]*accmdl.Info)
- for _, bm := range bms {
- for mid, info := range bm {
- res[mid] = info
- }
- }
- return
- }
|