123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- package service
- import (
- "context"
- "sort"
- "time"
- artmdl "go-common/app/interface/openplatform/article/model"
- "go-common/app/job/openplatform/article/dao"
- "go-common/app/job/openplatform/article/model"
- "go-common/library/log"
- )
- var (
- _recommendCategory = int64(0)
- )
- // UpdateSort update sort
- func (s *Service) UpdateSort(c context.Context) (err error) {
- ids := []int64{_recommendCategory}
- for id := range s.categoriesMap {
- ids = append(ids, id)
- }
- var (
- cache bool
- allArts map[int64]map[int][][2]int64
- )
- for _, categoryID := range ids {
- for _, field := range artmdl.SortFields {
- if (categoryID == _recommendCategory) && (field != artmdl.FieldNew) {
- continue
- }
- if cache, err = s.dao.ExpireSortCache(c, categoryID, field); err != nil {
- dao.PromError("recommends:更新文章排序")
- return
- }
- // cache不存在才更新
- if cache {
- continue
- }
- dao.PromInfo("sort:初始化排序缓存")
- if allArts == nil {
- allArts, _ = s.loadSortArts(context.TODO())
- }
- if field == artmdl.FieldNew {
- s.updateNewArts(c, categoryID)
- } else {
- s.updateStatSort(c, allArts, categoryID, field)
- }
- }
- }
- return
- }
- func (s *Service) updateNewArts(c context.Context, categoryID int64) (err error) {
- var arts [][2]int64
- if categoryID == _recommendCategory {
- if arts, err = s.dao.NewestArtIDs(c, s.c.Job.MaxNewArtsNum); err == nil {
- log.Info("s.updateNewArts() len: %v", len(arts))
- // 不异步
- err = s.dao.AddSortCaches(c, _recommendCategory, artmdl.FieldNew, arts, s.c.Job.MaxNewArtsNum)
- }
- return
- }
- ids := []int64{}
- cs := s.categoriesReverseMap[categoryID]
- if len(cs) == 0 {
- // 二级分区
- ids = append(ids, categoryID)
- } else {
- // 一级分区聚合子分区
- for _, s := range cs {
- ids = append(ids, s.ID)
- }
- }
- if arts, err = s.dao.NewestArtIDByCategory(c, ids, s.c.Job.MaxNewArtsNum); err == nil {
- // 不异步
- err = s.dao.AddSortCaches(c, categoryID, artmdl.FieldNew, arts, s.c.Job.MaxNewArtsNum)
- }
- return
- }
- func (s *Service) updateStatSort(c context.Context, allArts map[int64]map[int][][2]int64, categoryID int64, field int) (err error) {
- if allArts == nil {
- return
- }
- if categoryID == _recommendCategory {
- //推荐下没有排序
- return
- }
- arts := trimArts(allArts[categoryID][field], int(s.c.Job.MaxSortArtsNum))
- err = s.dao.AddSortCaches(c, categoryID, field, arts, s.c.Job.MaxSortArtsNum)
- return
- }
- func trimArts(arts [][2]int64, max int) (res [][2]int64) {
- sort.Slice(arts, func(i, j int) bool {
- return arts[i][1] > arts[j][1]
- })
- if len(arts) > max {
- return arts[:max]
- }
- return arts
- }
- func (s *Service) loadSortArts(c context.Context) (res map[int64]map[int][][2]int64, err error) {
- // init category and field
- res = make(map[int64]map[int][][2]int64)
- for id := range s.categoriesMap {
- res[id] = make(map[int][][2]int64)
- }
- var (
- arts []*model.SearchArticle
- limitTime = time.Now().Unix() - s.sortLimitTime
- )
- if arts, err = s.dao.SearchArts(c, limitTime); err != nil {
- dao.PromError("sort:初始化排序计数失败")
- return
- }
- for _, art := range arts {
- if artmdl.NoDistributeAttr(art.Attributes) || artmdl.NoRegionAttr(art.Attributes) {
- continue
- }
- if res[art.CategoryID] == nil {
- res[art.CategoryID] = make(map[int][][2]int64)
- }
- res[art.CategoryID][artmdl.FieldFav] = append(res[art.CategoryID][artmdl.FieldFav], [2]int64{art.ID, art.StatsFavorite})
- res[art.CategoryID][artmdl.FieldLike] = append(res[art.CategoryID][artmdl.FieldLike], [2]int64{art.ID, art.StatsLikes})
- res[art.CategoryID][artmdl.FieldReply] = append(res[art.CategoryID][artmdl.FieldReply], [2]int64{art.ID, art.StatsReply})
- res[art.CategoryID][artmdl.FieldView] = append(res[art.CategoryID][artmdl.FieldView], [2]int64{art.ID, art.StatsView})
- var parentID int64
- if id, ok := s.categoriesMap[art.CategoryID]; ok {
- parentID = id.ParentID
- } else {
- continue
- }
- if res[parentID] == nil {
- res[parentID] = make(map[int][][2]int64)
- }
- res[parentID][artmdl.FieldFav] = append(res[parentID][artmdl.FieldFav], [2]int64{art.ID, art.StatsFavorite})
- res[parentID][artmdl.FieldLike] = append(res[parentID][artmdl.FieldLike], [2]int64{art.ID, art.StatsLikes})
- res[parentID][artmdl.FieldReply] = append(res[parentID][artmdl.FieldReply], [2]int64{art.ID, art.StatsReply})
- res[parentID][artmdl.FieldView] = append(res[parentID][artmdl.FieldView], [2]int64{art.ID, art.StatsView})
- }
- return
- }
- func (s *Service) loadCategoriesproc() {
- for {
- time.Sleep(time.Minute * 10)
- s.loadCategories()
- }
- }
- func (s *Service) loadCategories() {
- for {
- c, err := s.articleRPC.CategoriesMap(context.TODO(), &artmdl.ArgIP{})
- if err != nil || len(c) == 0 {
- dao.PromError("service:获取分类")
- log.Error("s.articleRPC.CategoriesMap err %v", err)
- time.Sleep(time.Second)
- continue
- }
- s.categoriesMap = c
- s.categoriesReverseMap = transformReverseCategory(c)
- return
- }
- }
- // 生成某个分类下的所有子分类
- func transformReverseCategory(cs map[int64]*artmdl.Category) (res map[int64][]*artmdl.Category) {
- res = make(map[int64][]*artmdl.Category)
- for _, c := range cs {
- n := c
- old := c
- for (n != nil) && (n.ParentID != 0) {
- res[n.ParentID] = append(res[n.ParentID], old)
- n = cs[n.ParentID]
- }
- }
- return
- }
|