You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
179 lines
4.2 KiB
179 lines
4.2 KiB
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 |
|
}
|
|
|