recommend_pool.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. package mcndao
  2. import (
  3. "context"
  4. "sort"
  5. "time"
  6. "go-common/app/interface/main/mcn/conf"
  7. "go-common/app/interface/main/mcn/dao/cache"
  8. "go-common/app/interface/main/mcn/dao/global"
  9. "go-common/app/interface/main/mcn/model/mcnmodel"
  10. "go-common/library/log"
  11. "github.com/bluele/gcache"
  12. )
  13. // RecommendPoolCache .
  14. type RecommendPoolCache struct {
  15. // map[tid] list
  16. UpTidMap map[int16][]*mcnmodel.McnGetRecommendPoolInfo
  17. TidTypeList []*mcnmodel.TidnameInfo
  18. }
  19. func (r *RecommendPoolCache) add(v *mcnmodel.McnGetRecommendPoolInfo) {
  20. if v == nil {
  21. return
  22. }
  23. if r.UpTidMap == nil {
  24. r.UpTidMap = make(map[int16][]*mcnmodel.McnGetRecommendPoolInfo)
  25. }
  26. r.UpTidMap[v.ActiveTid] = append(r.UpTidMap[v.ActiveTid], v)
  27. if v.ActiveTid != 0 {
  28. // 加入到全部分类中
  29. r.UpTidMap[0] = append(r.UpTidMap[0], v)
  30. }
  31. }
  32. //RecommendSortFunc sort func
  33. type RecommendSortFunc func(p1, p2 *mcnmodel.McnGetRecommendPoolInfo) bool
  34. //RecommendDataSorter data sorter
  35. type RecommendDataSorter struct {
  36. Datas []*mcnmodel.McnGetRecommendPoolInfo
  37. By RecommendSortFunc // Closure used in the Less method.
  38. }
  39. // Len is part of sort.Interface.
  40. func (s *RecommendDataSorter) Len() int {
  41. return len(s.Datas)
  42. }
  43. // Swap is part of sort.Interface.
  44. func (s *RecommendDataSorter) Swap(i, j int) {
  45. s.Datas[i], s.Datas[j] = s.Datas[j], s.Datas[i]
  46. }
  47. // Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter.
  48. func (s *RecommendDataSorter) Less(i, j int) bool {
  49. return s.By(s.Datas[i], s.Datas[j])
  50. }
  51. // RecommendSortByFansDesc .
  52. func RecommendSortByFansDesc(p1, p2 *mcnmodel.McnGetRecommendPoolInfo) bool {
  53. return p1.FansCount > p2.FansCount
  54. }
  55. // RecommendSortByFansAsc .
  56. func RecommendSortByFansAsc(p1, p2 *mcnmodel.McnGetRecommendPoolInfo) bool {
  57. return p1.FansCount < p2.FansCount
  58. }
  59. // RecommendSortByMonthFansDesc .
  60. func RecommendSortByMonthFansDesc(p1, p2 *mcnmodel.McnGetRecommendPoolInfo) bool {
  61. return p1.FansCountIncreaseMonth > p2.FansCountIncreaseMonth
  62. }
  63. // RecommendSortByArchiveCountDesc .
  64. func RecommendSortByArchiveCountDesc(p1, p2 *mcnmodel.McnGetRecommendPoolInfo) bool {
  65. return p1.ArchiveCount > p2.ArchiveCount
  66. }
  67. type loadRecommandFunc func() (res *RecommendPoolCache, err error)
  68. func cacheKeyRecommend(int64) string {
  69. return "recommend"
  70. }
  71. //rawGetRecommendPool get recommend pool
  72. func (d *Dao) rawGetRecommendPool() (res []*mcnmodel.McnGetRecommendPoolInfo, err error) {
  73. var dbresult []*mcnmodel.McnUpRecommendPool
  74. err = d.mcndb.Where("state=?", mcnmodel.MCNUPRecommendStateOn).Find(&dbresult).Error
  75. if err != nil {
  76. log.Error("fail to get recommend pool, err=%s", err)
  77. return
  78. }
  79. for _, v := range dbresult {
  80. var info = &mcnmodel.McnGetRecommendPoolInfo{}
  81. info.Copy(v)
  82. res = append(res, info)
  83. }
  84. return
  85. }
  86. func (d *Dao) loadRecommendPool() (res *RecommendPoolCache, err error) {
  87. recommendInfos, err := d.rawGetRecommendPool()
  88. if err != nil {
  89. log.Error("get recommend fail, err=%s", err)
  90. return
  91. }
  92. var midMap = make(map[int64]struct{})
  93. // 获取mid列表
  94. for _, v := range recommendInfos {
  95. midMap[v.UpMid] = struct{}{}
  96. }
  97. var mids []int64
  98. for k := range midMap {
  99. mids = append(mids, k)
  100. }
  101. // 获取账号信息,头像
  102. accInfos, err := global.GetInfos(context.Background(), mids)
  103. if err != nil || accInfos == nil {
  104. log.Warn("get infos fail, err=%s", err)
  105. }
  106. var tidUnique = newTidNameUnique()
  107. res = new(RecommendPoolCache)
  108. for _, v := range recommendInfos {
  109. if account, ok := accInfos[v.UpMid]; ok {
  110. v.UpName = account.Name
  111. }
  112. v.TidName = cache.GetTidName(int64(v.ActiveTid))
  113. // 这里DataTypeAccumulate只是用来记录一下
  114. tidUnique.addTid(v.ActiveTid, v.TidName, mcnmodel.DataTypeAccumulate)
  115. res.add(v)
  116. }
  117. res.TidTypeList = tidUnique.getList(mcnmodel.DataTypeAccumulate)
  118. // 进行默认排序,按照粉丝数,降序
  119. for k := range res.UpTidMap {
  120. sort.Sort(&RecommendDataSorter{Datas: res.UpTidMap[k], By: RecommendSortByFansDesc})
  121. }
  122. return
  123. }
  124. func (d *Dao) getRecommendCache(keyCalc keyFunc, load loadRecommandFunc) (result *RecommendPoolCache, err error) {
  125. var key = keyCalc(0)
  126. v, err := d.localcache.Get(key)
  127. if err != nil {
  128. if err == gcache.KeyNotFoundError {
  129. // load cache
  130. v, err = load()
  131. if err != nil {
  132. log.Error("load cache error, key=%s. err=%s", key, err)
  133. return
  134. }
  135. d.localcache.SetWithExpire(key, v, time.Duration(conf.Conf.RankCache.RecommendPoolExpireTime))
  136. } else {
  137. log.Error("get from gcache err, key=%s, err=%s", key, err)
  138. return
  139. }
  140. }
  141. if v == nil {
  142. return
  143. }
  144. result, _ = v.(*RecommendPoolCache)
  145. return
  146. }
  147. //GetRecommendPool get recommend pool
  148. func (d *Dao) GetRecommendPool() (res *RecommendPoolCache, err error) {
  149. res, err = d.getRecommendCache(cacheKeyRecommend, d.loadRecommendPool)
  150. if err != nil {
  151. log.Error("fail to get recommend pool, err=%s", err)
  152. return
  153. }
  154. return
  155. }