upper.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. package service
  2. import (
  3. "context"
  4. "sort"
  5. "sync"
  6. "go-common/app/interface/openplatform/article/dao"
  7. artmdl "go-common/app/interface/openplatform/article/model"
  8. "go-common/library/log"
  9. "go-common/library/sync/errgroup"
  10. )
  11. // UpArticleMetas list up article metas
  12. func (s *Service) UpArticleMetas(c context.Context, mid int64, pn int, ps int, sortType int) (res *artmdl.UpArtMetas, err error) {
  13. var (
  14. ups map[int64][]*artmdl.Meta
  15. start = (pn - 1) * ps
  16. end = start + ps - 1 // from cache, end-1
  17. metas []*artmdl.Meta
  18. )
  19. if sortType == artmdl.FieldDefault {
  20. ups, err = s.UpsArticleMetas(c, []int64{mid}, start, end)
  21. } else {
  22. ups, err = s.UpsArticleMetas(c, []int64{mid}, 0, -1)
  23. }
  24. if err != nil {
  25. return
  26. }
  27. metas = ups[mid]
  28. if sortType != artmdl.FieldDefault {
  29. end++
  30. switch sortType {
  31. case artmdl.FieldFav:
  32. sort.Slice(metas, func(i, j int) bool { return metas[i].Stats.Favorite > metas[j].Stats.Favorite })
  33. case artmdl.FieldView:
  34. sort.Slice(metas, func(i, j int) bool { return metas[i].Stats.View > metas[j].Stats.View })
  35. }
  36. if start > len(metas) {
  37. start = len(metas)
  38. }
  39. if end > len(metas) {
  40. end = len(metas)
  41. }
  42. metas = metas[start:end]
  43. }
  44. res = new(artmdl.UpArtMetas)
  45. res.Articles = filterNoDistributeArts(metas)
  46. res.Pn = pn
  47. res.Ps = ps
  48. if res.Count, err = s.UpperArtsCount(c, mid); err != nil {
  49. dao.PromError("upper:获取作者文章数")
  50. }
  51. return
  52. }
  53. // UpsArticleMetas list up article metas
  54. func (s *Service) UpsArticleMetas(c context.Context, mids []int64, start int, end int) (res map[int64][]*artmdl.Meta, err error) {
  55. var (
  56. group = &errgroup.Group{}
  57. mutex = &sync.Mutex{}
  58. )
  59. res = make(map[int64][]*artmdl.Meta)
  60. upArtIDs, _ := s.upArtIDs(c, mids, start, end)
  61. for mid, ids := range upArtIDs {
  62. mid := mid
  63. ids := ids
  64. group.Go(func() (err error) {
  65. var (
  66. artsm map[int64]*artmdl.Meta
  67. arts []*artmdl.Meta
  68. )
  69. artsm, _ = s.FeedArticleMetas(c, ids)
  70. for _, art := range artsm {
  71. arts = append(arts, art)
  72. }
  73. mutex.Lock()
  74. sort.Sort(artmdl.Metas(arts))
  75. res[mid] = arts
  76. mutex.Unlock()
  77. return
  78. })
  79. }
  80. group.Wait()
  81. return
  82. }
  83. func (s *Service) upArtIDs(c context.Context, mids []int64, start, end int) (res map[int64][]int64, err error) {
  84. var (
  85. exists map[int64]bool
  86. addCache = true
  87. missMids = make([]int64, 0, len(mids))
  88. cacheMids = make([]int64, 0, len(mids))
  89. group = &errgroup.Group{}
  90. cacheUpArtIDs map[int64][]int64
  91. missUpArts map[int64][][2]int64
  92. // missUpArtIDs map[int64][][2]int64
  93. )
  94. res = make(map[int64][]int64)
  95. if exists, err = s.dao.ExpireUppersCache(c, mids); err != nil {
  96. addCache = false
  97. err = nil
  98. }
  99. for _, mid := range mids {
  100. if !exists[mid] {
  101. missMids = append(missMids, mid)
  102. } else {
  103. cacheMids = append(cacheMids, mid)
  104. }
  105. }
  106. // from cache
  107. group.Go(func() (err error) {
  108. if cacheUpArtIDs, err = s.dao.UppersCaches(c, cacheMids, start, end); err != nil {
  109. dao.PromError("upper:获取up主文章列表")
  110. }
  111. return
  112. })
  113. group.Go(func() (err error) {
  114. if len(missMids) > 0 {
  115. missUpArts, err = s.dao.UppersPassed(c, missMids)
  116. }
  117. return
  118. })
  119. group.Wait()
  120. for mid, ids := range cacheUpArtIDs {
  121. res[mid] = ids
  122. }
  123. for mid, arts := range missUpArts {
  124. var ids []int64
  125. for _, art := range arts {
  126. ids = append(ids, art[0])
  127. }
  128. if (start == 0) && (end == -1) {
  129. res[mid] = ids
  130. continue
  131. }
  132. if len(ids) <= start {
  133. res[mid] = []int64{}
  134. continue
  135. }
  136. if len(ids) < end {
  137. res[mid] = ids[start:]
  138. } else {
  139. res[mid] = ids[start:end]
  140. }
  141. }
  142. if addCache && (len(missUpArts) > 0) {
  143. s.dao.AddUpperCaches(c, missUpArts)
  144. }
  145. return
  146. }
  147. // UpperArtsCount count upper article
  148. func (s *Service) UpperArtsCount(c context.Context, mid int64) (res int, err error) {
  149. var (
  150. exists map[int64]bool
  151. arts map[int64][][2]int64
  152. )
  153. if exists, err = s.dao.ExpireUppersCache(c, []int64{mid}); err != nil {
  154. err = nil
  155. return
  156. }
  157. if exists[mid] {
  158. if res, err = s.dao.UpperArtsCountCache(c, mid); err == nil {
  159. return
  160. }
  161. log.Error("s.dao.UpperArtsCountCache(%v) err: %+v", mid, err)
  162. }
  163. if arts, err = s.dao.UppersPassed(c, []int64{mid}); err != nil {
  164. dao.PromError("upper:获取作者文章列表")
  165. return
  166. }
  167. res = len(arts[mid])
  168. cache.Save(func() {
  169. s.dao.AddUpperCaches(context.TODO(), arts)
  170. })
  171. return
  172. }