go-common/app/interface/openplatform/article/service/upper.go
2019-04-22 18:49:16 +08:00

180 lines
4.2 KiB
Go

package service
import (
"context"
"sort"
"sync"
"go-common/app/interface/openplatform/article/dao"
artmdl "go-common/app/interface/openplatform/article/model"
"go-common/library/log"
"go-common/library/sync/errgroup"
)
// UpArticleMetas list up article metas
func (s *Service) UpArticleMetas(c context.Context, mid int64, pn int, ps int, sortType int) (res *artmdl.UpArtMetas, err error) {
var (
ups map[int64][]*artmdl.Meta
start = (pn - 1) * ps
end = start + ps - 1 // from cache, end-1
metas []*artmdl.Meta
)
if sortType == artmdl.FieldDefault {
ups, err = s.UpsArticleMetas(c, []int64{mid}, start, end)
} else {
ups, err = s.UpsArticleMetas(c, []int64{mid}, 0, -1)
}
if err != nil {
return
}
metas = ups[mid]
if sortType != artmdl.FieldDefault {
end++
switch sortType {
case artmdl.FieldFav:
sort.Slice(metas, func(i, j int) bool { return metas[i].Stats.Favorite > metas[j].Stats.Favorite })
case artmdl.FieldView:
sort.Slice(metas, func(i, j int) bool { return metas[i].Stats.View > metas[j].Stats.View })
}
if start > len(metas) {
start = len(metas)
}
if end > len(metas) {
end = len(metas)
}
metas = metas[start:end]
}
res = new(artmdl.UpArtMetas)
res.Articles = filterNoDistributeArts(metas)
res.Pn = pn
res.Ps = ps
if res.Count, err = s.UpperArtsCount(c, mid); err != nil {
dao.PromError("upper:获取作者文章数")
}
return
}
// UpsArticleMetas list up article metas
func (s *Service) UpsArticleMetas(c context.Context, mids []int64, start int, end int) (res map[int64][]*artmdl.Meta, err error) {
var (
group = &errgroup.Group{}
mutex = &sync.Mutex{}
)
res = make(map[int64][]*artmdl.Meta)
upArtIDs, _ := s.upArtIDs(c, mids, start, end)
for mid, ids := range upArtIDs {
mid := mid
ids := ids
group.Go(func() (err error) {
var (
artsm map[int64]*artmdl.Meta
arts []*artmdl.Meta
)
artsm, _ = s.FeedArticleMetas(c, ids)
for _, art := range artsm {
arts = append(arts, art)
}
mutex.Lock()
sort.Sort(artmdl.Metas(arts))
res[mid] = arts
mutex.Unlock()
return
})
}
group.Wait()
return
}
func (s *Service) upArtIDs(c context.Context, mids []int64, start, end int) (res map[int64][]int64, err error) {
var (
exists map[int64]bool
addCache = true
missMids = make([]int64, 0, len(mids))
cacheMids = make([]int64, 0, len(mids))
group = &errgroup.Group{}
cacheUpArtIDs map[int64][]int64
missUpArts map[int64][][2]int64
// missUpArtIDs map[int64][][2]int64
)
res = make(map[int64][]int64)
if exists, err = s.dao.ExpireUppersCache(c, mids); err != nil {
addCache = false
err = nil
}
for _, mid := range mids {
if !exists[mid] {
missMids = append(missMids, mid)
} else {
cacheMids = append(cacheMids, mid)
}
}
// from cache
group.Go(func() (err error) {
if cacheUpArtIDs, err = s.dao.UppersCaches(c, cacheMids, start, end); err != nil {
dao.PromError("upper:获取up主文章列表")
}
return
})
group.Go(func() (err error) {
if len(missMids) > 0 {
missUpArts, err = s.dao.UppersPassed(c, missMids)
}
return
})
group.Wait()
for mid, ids := range cacheUpArtIDs {
res[mid] = ids
}
for mid, arts := range missUpArts {
var ids []int64
for _, art := range arts {
ids = append(ids, art[0])
}
if (start == 0) && (end == -1) {
res[mid] = ids
continue
}
if len(ids) <= start {
res[mid] = []int64{}
continue
}
if len(ids) < end {
res[mid] = ids[start:]
} else {
res[mid] = ids[start:end]
}
}
if addCache && (len(missUpArts) > 0) {
s.dao.AddUpperCaches(c, missUpArts)
}
return
}
// UpperArtsCount count upper article
func (s *Service) UpperArtsCount(c context.Context, mid int64) (res int, err error) {
var (
exists map[int64]bool
arts map[int64][][2]int64
)
if exists, err = s.dao.ExpireUppersCache(c, []int64{mid}); err != nil {
err = nil
return
}
if exists[mid] {
if res, err = s.dao.UpperArtsCountCache(c, mid); err == nil {
return
}
log.Error("s.dao.UpperArtsCountCache(%v) err: %+v", mid, err)
}
if arts, err = s.dao.UppersPassed(c, []int64{mid}); err != nil {
dao.PromError("upper:获取作者文章列表")
return
}
res = len(arts[mid])
cache.Save(func() {
s.dao.AddUpperCaches(context.TODO(), arts)
})
return
}