781 lines
20 KiB
Go
781 lines
20 KiB
Go
|
package like
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"context"
|
||
|
"strconv"
|
||
|
"sync"
|
||
|
|
||
|
dao "go-common/app/interface/main/activity/dao/like"
|
||
|
likemdl "go-common/app/interface/main/activity/model/like"
|
||
|
tagmdl "go-common/app/interface/main/tag/model"
|
||
|
"go-common/app/service/main/archive/api"
|
||
|
"go-common/app/service/main/archive/model/archive"
|
||
|
thpmdl "go-common/app/service/main/thumbup/model"
|
||
|
"go-common/library/ecode"
|
||
|
"go-common/library/log"
|
||
|
"go-common/library/sync/errgroup"
|
||
|
"go-common/library/xstr"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
_aidBulkSize = 100
|
||
|
_tagBlkSize = 50
|
||
|
_tagArcType = 3
|
||
|
_tagLikePoint = 100
|
||
|
_orderTypeCtime = "ctime"
|
||
|
_orderTypeRandom = "random"
|
||
|
_specialLikeRate = 1000
|
||
|
_businessLike = "archive"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
_emptyLikeList = make([]*likemdl.Like, 0)
|
||
|
_emptyArcs = make([]*api.Arc, 0)
|
||
|
)
|
||
|
|
||
|
// UpdateActSourceList update act arc list.
|
||
|
func (s *Service) updateActSourceList(c context.Context, sid int64, typ string) (err error) {
|
||
|
var (
|
||
|
likes []*likemdl.Item
|
||
|
)
|
||
|
if likes, err = s.dao.LikeList(c, sid); err != nil {
|
||
|
log.Error("UpdateActSourceList s.dao.LikeList(%d) error(%v)", sid, err)
|
||
|
return
|
||
|
}
|
||
|
s.cache.Do(c, func(c context.Context) {
|
||
|
if typ == _typeAll {
|
||
|
s.updateActCacheList(c, sid, likes)
|
||
|
}
|
||
|
if typ == _typeRegion {
|
||
|
s.updateActRegionList(c, sid, likes)
|
||
|
}
|
||
|
})
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func (s *Service) updateActCacheList(c context.Context, sid int64, likes []*likemdl.Item) (err error) {
|
||
|
var (
|
||
|
aids []int64
|
||
|
tags map[int64][]*tagmdl.Tag
|
||
|
arcs map[int64]*api.Arc
|
||
|
)
|
||
|
likeMap := make(map[int64]*likemdl.Item, len(likes))
|
||
|
for _, v := range likes {
|
||
|
if v.Wid > 0 {
|
||
|
aids = append(aids, v.Wid)
|
||
|
likeMap[v.Wid] = v
|
||
|
}
|
||
|
}
|
||
|
if len(aids) == 0 {
|
||
|
return
|
||
|
}
|
||
|
if tags, err = s.arcTags(c, aids); err != nil {
|
||
|
return
|
||
|
}
|
||
|
if arcs, err = s.archives(c, aids); err != nil {
|
||
|
return
|
||
|
}
|
||
|
arcTagMap := make(map[int64][]*likemdl.Item, len(s.dialectTags))
|
||
|
tagLikePtTmp := make(map[int64]int32, len(s.dialectTags))
|
||
|
for aid, arcTag := range tags {
|
||
|
for _, tag := range arcTag {
|
||
|
if _, ok := s.dialectTags[tag.ID]; ok {
|
||
|
arcTagMap[tag.ID] = append(arcTagMap[tag.ID], likeMap[aid])
|
||
|
if arc, ok := arcs[aid]; ok && arc.IsNormal() {
|
||
|
tagLikePtTmp[tag.ID] += arc.Stat.Like
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
tagPtMap := make(map[int64]int32, len(s.dialectTags))
|
||
|
for tagID, v := range arcTagMap {
|
||
|
s.dao.SetLikeTagCache(c, sid, tagID, v)
|
||
|
if like, ok := tagLikePtTmp[tagID]; ok {
|
||
|
tagPt := int32(len(v)*_tagLikePoint) + like
|
||
|
tagPtMap[tagID] = tagPt
|
||
|
}
|
||
|
}
|
||
|
s.dao.SetTagLikeCountsCache(c, sid, tagPtMap)
|
||
|
regionMap := make(map[int16][]*likemdl.Item, len(s.dialectRegions))
|
||
|
for _, arc := range arcs {
|
||
|
if region, ok := s.arcType[int16(arc.TypeID)]; ok {
|
||
|
if _, ok := s.dialectRegions[region.Pid]; ok {
|
||
|
regionMap[region.Pid] = append(regionMap[region.Pid], likeMap[arc.Aid])
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
for rid, v := range regionMap {
|
||
|
s.dao.SetLikeRegionCache(c, sid, rid, v)
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func (s *Service) updateActRegionList(c context.Context, sid int64, likes []*likemdl.Item) (err error) {
|
||
|
var (
|
||
|
aids []int64
|
||
|
arcs map[int64]*api.Arc
|
||
|
)
|
||
|
likeMap := make(map[int64]*likemdl.Item, len(likes))
|
||
|
for _, v := range likes {
|
||
|
if v.Wid > 0 {
|
||
|
aids = append(aids, v.Wid)
|
||
|
likeMap[v.Wid] = v
|
||
|
}
|
||
|
}
|
||
|
if len(aids) == 0 {
|
||
|
return
|
||
|
}
|
||
|
if arcs, err = s.archives(c, aids); err != nil {
|
||
|
return
|
||
|
}
|
||
|
regionMap := make(map[int16][]*likemdl.Item)
|
||
|
for _, arc := range arcs {
|
||
|
if region, ok := s.arcType[int16(arc.TypeID)]; ok {
|
||
|
regionMap[region.Pid] = append(regionMap[region.Pid], likeMap[arc.Aid])
|
||
|
}
|
||
|
}
|
||
|
for rid, v := range regionMap {
|
||
|
s.dao.SetLikeRegionCache(c, sid, rid, v)
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func (s *Service) archives(c context.Context, aids []int64) (archives map[int64]*api.Arc, err error) {
|
||
|
var (
|
||
|
mutex = sync.Mutex{}
|
||
|
aidsLen = len(aids)
|
||
|
group, errCtx = errgroup.WithContext(c)
|
||
|
)
|
||
|
archives = make(map[int64]*api.Arc, aidsLen)
|
||
|
for i := 0; i < aidsLen; i += _aidBulkSize {
|
||
|
var partAids []int64
|
||
|
if i+_aidBulkSize > aidsLen {
|
||
|
partAids = aids[i:]
|
||
|
} else {
|
||
|
partAids = aids[i : i+_aidBulkSize]
|
||
|
}
|
||
|
group.Go(func() (err error) {
|
||
|
var arcs map[int64]*api.Arc
|
||
|
arg := &archive.ArgAids2{Aids: partAids}
|
||
|
if arcs, err = s.arcRPC.Archives3(errCtx, arg); err != nil {
|
||
|
log.Error("s.arcRPC.Archives(%v) error(%v)", partAids, err)
|
||
|
return
|
||
|
}
|
||
|
mutex.Lock()
|
||
|
for _, v := range arcs {
|
||
|
archives[v.Aid] = v
|
||
|
}
|
||
|
mutex.Unlock()
|
||
|
return
|
||
|
})
|
||
|
}
|
||
|
err = group.Wait()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func (s *Service) arcTags(c context.Context, aids []int64) (tags map[int64][]*tagmdl.Tag, err error) {
|
||
|
var (
|
||
|
tagErr error
|
||
|
mutex = sync.Mutex{}
|
||
|
)
|
||
|
group, errCtx := errgroup.WithContext(c)
|
||
|
aidsLen := len(aids)
|
||
|
tags = make(map[int64][]*tagmdl.Tag, aidsLen)
|
||
|
for i := 0; i < aidsLen; i += _tagBlkSize {
|
||
|
var partAids []int64
|
||
|
if i+_tagBlkSize > aidsLen {
|
||
|
partAids = aids[i:]
|
||
|
} else {
|
||
|
partAids = aids[i : i+_tagBlkSize]
|
||
|
}
|
||
|
group.Go(func() (err error) {
|
||
|
var tmpRes map[int64][]*tagmdl.Tag
|
||
|
arg := &tagmdl.ArgResTags{Oids: partAids, Type: _tagArcType}
|
||
|
if tmpRes, tagErr = s.tagRPC.ResTags(errCtx, arg); tagErr != nil {
|
||
|
dao.PromError("ResTags接口错误", "s.tag.ResTag(%+v) error(%v)", arg, tagErr)
|
||
|
return
|
||
|
}
|
||
|
mutex.Lock()
|
||
|
for aid, tmpTags := range tmpRes {
|
||
|
tags[aid] = tmpTags
|
||
|
}
|
||
|
mutex.Unlock()
|
||
|
return nil
|
||
|
})
|
||
|
}
|
||
|
group.Wait()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// TagArcList tag arc list.
|
||
|
func (s *Service) TagArcList(c context.Context, sid, tagID int64, pn, ps int, typ, ip string) (list []*likemdl.Like, cnt int, err error) {
|
||
|
var (
|
||
|
likes []*likemdl.Item
|
||
|
start, end int
|
||
|
aids []int64
|
||
|
archives map[int64]*api.Arc
|
||
|
)
|
||
|
if sid != s.c.Rule.DialectSid {
|
||
|
err = ecode.RequestErr
|
||
|
return
|
||
|
}
|
||
|
if _, ok := s.dialectTags[tagID]; !ok {
|
||
|
err = ecode.RequestErr
|
||
|
return
|
||
|
}
|
||
|
if cnt, err = s.dao.LikeTagCnt(c, sid, tagID); err != nil {
|
||
|
log.Error("TagArcList s.dao.LikeTagCnt sid(%d) tagID(%d) error(%v)", sid, tagID, err)
|
||
|
return
|
||
|
}
|
||
|
if start, end, err = s.fmtStartEnd(pn, ps, cnt, typ); err != nil {
|
||
|
err = nil
|
||
|
list = _emptyLikeList
|
||
|
return
|
||
|
}
|
||
|
if likes, err = s.dao.LikeTagCache(c, sid, tagID, start, end); err != nil {
|
||
|
log.Error("TagArcList s.dao.LikeTagCache sid(%d) tagID(%d) start(%d) end(%d) error(%+v)", sid, tagID, start, end, err)
|
||
|
return
|
||
|
}
|
||
|
for _, v := range likes {
|
||
|
if v.Wid > 0 {
|
||
|
aids = append(aids, v.Wid)
|
||
|
}
|
||
|
}
|
||
|
if len(aids) == 0 {
|
||
|
list = _emptyLikeList
|
||
|
return
|
||
|
}
|
||
|
if archives, err = s.arcRPC.Archives3(c, &archive.ArgAids2{Aids: aids, RealIP: ip}); err != nil {
|
||
|
log.Error("TagArcList s.arcRPC.Archives3 aids(%v) error(%+v)", aids, err)
|
||
|
return
|
||
|
}
|
||
|
for _, v := range likes {
|
||
|
if arc, ok := archives[v.Wid]; ok && arc.IsNormal() {
|
||
|
list = append(list, &likemdl.Like{Item: v, Archive: arc})
|
||
|
}
|
||
|
}
|
||
|
l := len(list)
|
||
|
if l == 0 {
|
||
|
list = _emptyLikeList
|
||
|
return
|
||
|
}
|
||
|
if typ == _orderTypeRandom {
|
||
|
s.shuffle(l, func(i, j int) {
|
||
|
list[i], list[j] = list[j], list[i]
|
||
|
})
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// RegionArcList region arc list.
|
||
|
func (s *Service) RegionArcList(c context.Context, sid int64, rid int16, pn, ps int, typ, ip string) (list []*likemdl.Like, cnt int, err error) {
|
||
|
var (
|
||
|
likes []*likemdl.Item
|
||
|
start, end int
|
||
|
aids []int64
|
||
|
archives map[int64]*api.Arc
|
||
|
)
|
||
|
if sid != s.c.Rule.DialectSid {
|
||
|
err = ecode.RequestErr
|
||
|
return
|
||
|
}
|
||
|
if _, ok := s.dialectRegions[rid]; !ok {
|
||
|
err = ecode.RequestErr
|
||
|
return
|
||
|
}
|
||
|
if cnt, err = s.dao.LikeRegionCnt(c, sid, rid); err != nil {
|
||
|
log.Error("RegionArcList s.dao.LikeRegionCnt sid(%d) rid(%d) error(%v)", sid, rid, err)
|
||
|
return
|
||
|
}
|
||
|
if start, end, err = s.fmtStartEnd(pn, ps, cnt, typ); err != nil {
|
||
|
err = nil
|
||
|
list = _emptyLikeList
|
||
|
return
|
||
|
}
|
||
|
if likes, err = s.dao.LikeRegionCache(c, sid, rid, start, end); err != nil {
|
||
|
log.Error("RegionArcList s.dao.LikeRegionCache sid(%d) rid(%d) start(%d) end(%d) error(%+v)", sid, rid, start, end, err)
|
||
|
return
|
||
|
}
|
||
|
for _, v := range likes {
|
||
|
if v.Wid > 0 {
|
||
|
aids = append(aids, v.Wid)
|
||
|
}
|
||
|
}
|
||
|
if len(aids) == 0 {
|
||
|
list = _emptyLikeList
|
||
|
return
|
||
|
}
|
||
|
if archives, err = s.arcRPC.Archives3(c, &archive.ArgAids2{Aids: aids, RealIP: ip}); err != nil {
|
||
|
log.Error("RegionArcList s.arcRPC.Archives3 aids(%v) error(%+v)", aids, err)
|
||
|
return
|
||
|
}
|
||
|
for _, v := range likes {
|
||
|
if arc, ok := archives[v.Wid]; ok && arc.IsNormal() {
|
||
|
list = append(list, &likemdl.Like{Item: v, Archive: arc})
|
||
|
}
|
||
|
}
|
||
|
l := len(list)
|
||
|
if l == 0 {
|
||
|
list = _emptyLikeList
|
||
|
return
|
||
|
}
|
||
|
if typ == _orderTypeRandom {
|
||
|
s.shuffle(l, func(i, j int) {
|
||
|
list[i], list[j] = list[j], list[i]
|
||
|
})
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// TagLikeCounts .
|
||
|
func (s *Service) TagLikeCounts(c context.Context, sid int64) (data map[int64]int32, err error) {
|
||
|
if sid != s.c.Rule.DialectSid {
|
||
|
err = ecode.RequestErr
|
||
|
return
|
||
|
}
|
||
|
return s.dao.TagLikeCountsCache(c, sid, s.c.Rule.DialectTags)
|
||
|
}
|
||
|
|
||
|
func (s *Service) fmtStartEnd(pn, ps, cnt int, typ string) (start, end int, err error) {
|
||
|
if typ == _orderTypeCtime {
|
||
|
start = (pn - 1) * ps
|
||
|
end = start + ps - 1
|
||
|
if start > cnt {
|
||
|
err = ecode.NothingFound
|
||
|
return
|
||
|
}
|
||
|
if end > cnt {
|
||
|
end = cnt
|
||
|
}
|
||
|
} else {
|
||
|
if ps >= cnt-1 {
|
||
|
start = 0
|
||
|
} else {
|
||
|
start = s.r.Intn(cnt - ps - 1)
|
||
|
}
|
||
|
end = start + ps - 1
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func (s *Service) shuffle(l int, swap func(i, j int)) {
|
||
|
for i := l - 1; i > 0; i-- {
|
||
|
j := s.r.Intn(i + 1)
|
||
|
swap(i, j)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// LikeInitialize initialize like cache data .
|
||
|
func (s *Service) LikeInitialize(c context.Context, lid int64) (err error) {
|
||
|
if lid < 0 {
|
||
|
lid = 0
|
||
|
}
|
||
|
var likesItem []*likemdl.Item
|
||
|
for {
|
||
|
if likesItem, err = s.dao.LikeListMoreLid(c, lid); err != nil {
|
||
|
log.Error("dao.LikeInitialize(%d) error(%+v)", lid, err)
|
||
|
break
|
||
|
}
|
||
|
if len(likesItem) == 0 {
|
||
|
log.Info("LikeInitialize end success")
|
||
|
break
|
||
|
}
|
||
|
for _, val := range likesItem {
|
||
|
item := val
|
||
|
if lid < item.ID {
|
||
|
lid = item.ID
|
||
|
}
|
||
|
id := item.ID
|
||
|
//the likes offline is stored with empty data
|
||
|
if item.State != 1 {
|
||
|
item = &likemdl.Item{}
|
||
|
}
|
||
|
s.cache.Do(c, func(c context.Context) {
|
||
|
s.dao.AddCacheLike(c, id, item)
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
s.cache.Do(c, func(c context.Context) {
|
||
|
s.LikeMaxIDInitialize(c)
|
||
|
})
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// LikeMaxIDInitialize likes max id initialize
|
||
|
func (s *Service) LikeMaxIDInitialize(c context.Context) (err error) {
|
||
|
var likeItem *likemdl.Item
|
||
|
if likeItem, err = s.dao.LikeMaxID(c); err != nil {
|
||
|
log.Error("s.dao.LikeMaxID() error(%+v)", err)
|
||
|
return
|
||
|
}
|
||
|
if likeItem.ID >= 0 {
|
||
|
if err = s.dao.AddCacheLikeMaxID(c, likeItem.ID); err != nil {
|
||
|
log.Error("s.dao.AddCacheLikeMaxID(%d),error(%v)", likeItem.ID, err)
|
||
|
}
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// LikeUp update likes cache and like maxID cache
|
||
|
func (s *Service) LikeUp(c context.Context, lid int64) (err error) {
|
||
|
var (
|
||
|
likeItem *likemdl.Item
|
||
|
likeMaxID int64
|
||
|
)
|
||
|
group, ctx := errgroup.WithContext(c)
|
||
|
group.Go(func() (e error) {
|
||
|
if likeItem, e = s.dao.RawLike(ctx, lid); e != nil {
|
||
|
log.Error("LikeUp:s.dao.RawLike(%d) error(%+v)", lid, e)
|
||
|
}
|
||
|
return
|
||
|
})
|
||
|
group.Go(func() (e error) {
|
||
|
if likeMaxID, e = s.dao.CacheLikeMaxID(ctx); e != nil {
|
||
|
log.Error("LikeUp:s.dao.CacheLikeMaxID() error(%v)", e)
|
||
|
}
|
||
|
return
|
||
|
})
|
||
|
if err = group.Wait(); err != nil {
|
||
|
log.Error("LikeUp: group.Wait() error(%v)", err)
|
||
|
return
|
||
|
}
|
||
|
if likeMaxID < lid {
|
||
|
s.cache.Do(c, func(c context.Context) {
|
||
|
s.dao.AddCacheLikeMaxID(c, lid)
|
||
|
})
|
||
|
}
|
||
|
if likeItem.ID == 0 {
|
||
|
likeItem = &likemdl.Item{}
|
||
|
}
|
||
|
s.cache.Do(c, func(c context.Context) {
|
||
|
s.dao.AddCacheLike(c, lid, likeItem)
|
||
|
})
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// AddLikeCtimeCache add cache .
|
||
|
func (s *Service) AddLikeCtimeCache(c context.Context, lid int64) (err error) {
|
||
|
var (
|
||
|
likeItem *likemdl.Item
|
||
|
cItems = make([]*likemdl.Item, 0, 1)
|
||
|
)
|
||
|
if likeItem, err = s.dao.RawLike(c, lid); err != nil {
|
||
|
log.Error("LikeUp:s.dao.RawLike(%d) error(%+v)", lid, err)
|
||
|
return
|
||
|
}
|
||
|
if likeItem.ID > 0 {
|
||
|
eg, errCtx := errgroup.WithContext(c)
|
||
|
cItems = append(cItems, likeItem)
|
||
|
eg.Go(func() (e error) {
|
||
|
e = s.dao.LikeListCtime(errCtx, likeItem.Sid, cItems)
|
||
|
return
|
||
|
})
|
||
|
eg.Go(func() (e error) {
|
||
|
// 初始化排行榜数据
|
||
|
e = s.dao.SetRedisCache(c, likeItem.Sid, lid, 0, likeItem.Type)
|
||
|
return
|
||
|
})
|
||
|
if err = eg.Wait(); err != nil {
|
||
|
log.Error("AddLikeCtimeCache eg.Wait() error(%+v)", err)
|
||
|
}
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// DelLikeCtimeCache delete ctime cache.
|
||
|
func (s *Service) DelLikeCtimeCache(c context.Context, lid, sid int64, likeType int) (err error) {
|
||
|
var (
|
||
|
cItems = make([]*likemdl.Item, 0, 1)
|
||
|
)
|
||
|
likeItem := &likemdl.Item{
|
||
|
ID: lid,
|
||
|
Sid: sid,
|
||
|
Type: likeType,
|
||
|
}
|
||
|
cItems = append(cItems, likeItem)
|
||
|
if err = s.dao.DelLikeListCtime(c, likeItem.Sid, cItems); err != nil {
|
||
|
log.Error("s.dao.DelLikeListCtime(%v) error (%v)", likeItem, err)
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// SubjectStat get subject stat .
|
||
|
func (s *Service) SubjectStat(c context.Context, sid int64) (score *likemdl.SubjectScore, err error) {
|
||
|
if sid == s.c.Rule.S8Sid {
|
||
|
var arcScore, artScore int64
|
||
|
group, errCtx := errgroup.WithContext(c)
|
||
|
group.Go(func() error {
|
||
|
var (
|
||
|
stat *likemdl.SubjectStat
|
||
|
arcErr error
|
||
|
)
|
||
|
if stat, arcErr = s.dao.CacheSubjectStat(errCtx, s.c.Rule.S8ArcSid); arcErr != nil {
|
||
|
log.Error("s.dao.CacheSubjectStat sid(%d) error(%v)", sid, arcErr)
|
||
|
}
|
||
|
if stat == nil {
|
||
|
stat = new(likemdl.SubjectStat)
|
||
|
}
|
||
|
arcScore = stat.Count*_specialLikeRate + stat.Like
|
||
|
return nil
|
||
|
})
|
||
|
group.Go(func() error {
|
||
|
var (
|
||
|
stat *likemdl.SubjectStat
|
||
|
artErr error
|
||
|
)
|
||
|
if stat, artErr = s.dao.CacheSubjectStat(errCtx, s.c.Rule.S8ArtSid); artErr != nil {
|
||
|
log.Error("s.dao.CacheSubjectStat sid(%d) error(%v)", sid, artErr)
|
||
|
}
|
||
|
if stat == nil {
|
||
|
stat = new(likemdl.SubjectStat)
|
||
|
}
|
||
|
artScore = stat.Count*_specialLikeRate + stat.Like
|
||
|
return nil
|
||
|
})
|
||
|
group.Wait()
|
||
|
score = &likemdl.SubjectScore{Score: arcScore + artScore}
|
||
|
} else {
|
||
|
var stat *likemdl.SubjectStat
|
||
|
if stat, err = s.dao.CacheSubjectStat(c, sid); err != nil {
|
||
|
log.Error("s.dao.CacheSubjectStat sid(%d) error(%v)", sid, err)
|
||
|
err = nil
|
||
|
}
|
||
|
if stat == nil {
|
||
|
stat = new(likemdl.SubjectStat)
|
||
|
}
|
||
|
if sid == s.c.Rule.KingStorySid {
|
||
|
score = &likemdl.SubjectScore{Score: stat.View + stat.Fav + stat.Coin + stat.Like}
|
||
|
} else {
|
||
|
score = &likemdl.SubjectScore{Score: stat.Count*_specialLikeRate + stat.Like}
|
||
|
}
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// SetSubjectStat set subject stat .
|
||
|
func (s *Service) SetSubjectStat(c context.Context, stat *likemdl.SubjectStat) (err error) {
|
||
|
return s.dao.AddCacheSubjectStat(c, stat.Sid, stat)
|
||
|
}
|
||
|
|
||
|
// ViewRank get view rank arcs.
|
||
|
func (s *Service) ViewRank(c context.Context, sid int64, pn, ps int) (list []*api.Arc, count int, err error) {
|
||
|
var (
|
||
|
aidsCache string
|
||
|
aids, pieceAids []int64
|
||
|
arcs map[int64]*api.Arc
|
||
|
)
|
||
|
if aidsCache, err = s.dao.CacheViewRank(c, sid); err != nil {
|
||
|
log.Error("ViewRank s.dao.CacheViewRank(%d) error(%v)", sid, err)
|
||
|
return
|
||
|
}
|
||
|
if aids, err = xstr.SplitInts(aidsCache); err != nil {
|
||
|
log.Error("ViewRank xstr.SplitInts(%d,%s) error(%v)", sid, aidsCache, err)
|
||
|
return
|
||
|
}
|
||
|
count = len(aids)
|
||
|
start := (pn - 1) * ps
|
||
|
end := start + ps - 1
|
||
|
if count < start {
|
||
|
list = _emptyArcs
|
||
|
return
|
||
|
}
|
||
|
if count > end {
|
||
|
pieceAids = aids[start : end+1]
|
||
|
} else {
|
||
|
pieceAids = aids[start:]
|
||
|
}
|
||
|
if arcs, err = s.arcRPC.Archives3(c, &archive.ArgAids2{Aids: pieceAids}); err != nil {
|
||
|
log.Error("ViewRank s.arcRPC.Archives3(%v) error(%v)", aids, err)
|
||
|
return
|
||
|
}
|
||
|
for _, aid := range pieceAids {
|
||
|
if arc, ok := arcs[aid]; ok && arc.IsNormal() {
|
||
|
list = append(list, arc)
|
||
|
}
|
||
|
}
|
||
|
if len(list) == 0 {
|
||
|
list = _emptyArcs
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// SetViewRank set view rank arcs.
|
||
|
func (s *Service) SetViewRank(c context.Context, sid int64, aids []int64) (err error) {
|
||
|
aidsStr := xstr.JoinInts(aids)
|
||
|
if err = s.dao.AddCacheViewRank(c, sid, aidsStr); err != nil {
|
||
|
log.Error("SetViewRank s.dao.AddCacheViewRank(%d,%s) error(%v)", sid, aidsStr, err)
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// ObjectGroup group like data.
|
||
|
func (s *Service) ObjectGroup(c context.Context, sid int64, ck string) (data map[int64][]*likemdl.GroupItem, err error) {
|
||
|
var sids []int64
|
||
|
if sids, err = s.dao.SourceItemData(c, sid); err != nil {
|
||
|
log.Error("ObjectGroup SourceItemData(%d) error(%+v)", sid, err)
|
||
|
return
|
||
|
}
|
||
|
if len(sids) == 0 {
|
||
|
log.Warn("ObjectGroup sid(%d) len(sids) == 0", sid)
|
||
|
err = ecode.NothingFound
|
||
|
return
|
||
|
}
|
||
|
data = make(map[int64][]*likemdl.GroupItem, len(sids))
|
||
|
group, errCtx := errgroup.WithContext(c)
|
||
|
mutex := sync.Mutex{}
|
||
|
for _, v := range sids {
|
||
|
groupSid := v
|
||
|
group.Go(func() error {
|
||
|
item, e := s.dao.GroupItemData(errCtx, groupSid, ck)
|
||
|
if e != nil {
|
||
|
log.Error("ObjectGroup s.dao.GroupItemData(%d) error(%+v)", groupSid, e)
|
||
|
} else {
|
||
|
mutex.Lock()
|
||
|
data[groupSid] = item
|
||
|
mutex.Unlock()
|
||
|
}
|
||
|
return nil
|
||
|
})
|
||
|
}
|
||
|
group.Wait()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// SetLikeContent .
|
||
|
func (s *Service) SetLikeContent(c context.Context, lid int64) (err error) {
|
||
|
var (
|
||
|
conts map[int64]*likemdl.LikeContent
|
||
|
)
|
||
|
if conts, err = s.dao.RawLikeContent(c, []int64{lid}); err != nil {
|
||
|
log.Error("s.dao.RawLikeContent(%d) error(%+v)", lid, err)
|
||
|
return
|
||
|
}
|
||
|
if _, ok := conts[lid]; !ok {
|
||
|
conts = make(map[int64]*likemdl.LikeContent, 1)
|
||
|
conts[lid] = &likemdl.LikeContent{}
|
||
|
}
|
||
|
if err = s.dao.AddCacheLikeContent(c, conts); err != nil {
|
||
|
log.Error("s.dao.AddCacheLikeContent(%d) error(%+v)", lid, err)
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// AddLikeActCache .
|
||
|
func (s *Service) AddLikeActCache(c context.Context, sid, lid, score int64) (err error) {
|
||
|
var (
|
||
|
likeItem *likemdl.Item
|
||
|
)
|
||
|
if likeItem, err = s.dao.Like(c, lid); err != nil {
|
||
|
log.Error("AddLikeActCache:s.dao.Like(%d) error(%+v)", lid, err)
|
||
|
return
|
||
|
}
|
||
|
if likeItem.ID == 0 {
|
||
|
return
|
||
|
}
|
||
|
if err = s.dao.SetRedisCache(c, sid, lid, score, likeItem.Type); err != nil {
|
||
|
log.Error("AddLikeActCache:s.dao.SetRedisCache(%d,%d,%d) error(%+v)", sid, lid, score, err)
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// LikeActCache .
|
||
|
func (s *Service) LikeActCache(c context.Context, sid, lid int64) (res int64, err error) {
|
||
|
return s.dao.LikeActZscore(c, sid, lid)
|
||
|
}
|
||
|
|
||
|
// BatchInsertLikeExtend batch insert like_extend table.
|
||
|
func (s *Service) BatchInsertLikeExtend(c context.Context, extends []*likemdl.Extend) (res int64, err error) {
|
||
|
var (
|
||
|
buf bytes.Buffer
|
||
|
cnt int
|
||
|
rows int64
|
||
|
)
|
||
|
for _, v := range extends {
|
||
|
buf.WriteString("(")
|
||
|
buf.WriteString(strconv.FormatInt(v.Lid, 10))
|
||
|
buf.WriteString(",")
|
||
|
buf.WriteString(strconv.FormatInt(v.Like, 10))
|
||
|
buf.WriteString("),")
|
||
|
cnt++
|
||
|
if cnt%500 == 0 {
|
||
|
buf.Truncate(buf.Len() - 1)
|
||
|
if rows, err = s.dao.AddExtend(c, buf.String()); err != nil {
|
||
|
log.Error("dao.dealAddExtend() error(%+v)", err)
|
||
|
return
|
||
|
}
|
||
|
res += rows
|
||
|
buf.Reset()
|
||
|
}
|
||
|
}
|
||
|
if buf.Len() > 0 {
|
||
|
buf.Truncate(buf.Len() - 1)
|
||
|
if rows, err = s.dao.AddExtend(c, buf.String()); err != nil {
|
||
|
log.Error("dao.dealAddExtend() error(%+v)", err)
|
||
|
return
|
||
|
}
|
||
|
res += rows
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// arcTag get archive and tags.
|
||
|
func (s *Service) arcTag(c context.Context, list []*likemdl.List, order string, mid int64) (err error) {
|
||
|
var (
|
||
|
arcsReply *api.ArcsReply
|
||
|
lt = len(list)
|
||
|
wids = make([]int64, 0, lt)
|
||
|
tagRes map[int64][]string
|
||
|
hasLikeList map[int64]int8
|
||
|
)
|
||
|
for _, v := range list {
|
||
|
if v.Wid > 0 {
|
||
|
wids = append(wids, v.Wid)
|
||
|
}
|
||
|
}
|
||
|
eg, errCtx := errgroup.WithContext(c)
|
||
|
eg.Go(func() (e error) {
|
||
|
arcsReply, e = s.arcClient.Arcs(errCtx, &api.ArcsRequest{Aids: wids})
|
||
|
return
|
||
|
})
|
||
|
eg.Go(func() (e error) {
|
||
|
tagRes, e = s.dao.MultiTags(errCtx, wids)
|
||
|
return
|
||
|
})
|
||
|
if mid != 0 && (order == dao.EsOrderLikes || order == dao.ActOrderCtime) {
|
||
|
eg.Go(func() (e error) {
|
||
|
hasLikeList, e = s.thumbup.HasLike(errCtx, &thpmdl.ArgHasLike{Business: _businessLike, MessageIDs: wids, Mid: mid})
|
||
|
return
|
||
|
})
|
||
|
}
|
||
|
if err = eg.Wait(); err != nil {
|
||
|
log.Error("arcTag:eg.Wait() error(%+v)", err)
|
||
|
return
|
||
|
}
|
||
|
for _, v := range list {
|
||
|
if v.Wid == 0 {
|
||
|
continue
|
||
|
}
|
||
|
obj := new(likemdl.ArgTag)
|
||
|
if _, ok := arcsReply.Arcs[v.Wid]; ok {
|
||
|
obj.Archive = arcsReply.Arcs[v.Wid]
|
||
|
}
|
||
|
if _, ok := tagRes[v.Wid]; ok {
|
||
|
obj.Tags = tagRes[v.Wid]
|
||
|
}
|
||
|
v.Object = obj
|
||
|
if _, ok := hasLikeList[v.Wid]; ok {
|
||
|
v.HasLikes = hasLikeList[v.Wid]
|
||
|
}
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// LikeOidsInfo .
|
||
|
func (s *Service) LikeOidsInfo(c context.Context, sType int, oids []int64) (res map[int64]*likemdl.Item, err error) {
|
||
|
if res, err = s.dao.OidInfoFromES(c, oids, sType); err != nil {
|
||
|
log.Error("s.dao.OidInfoFromES(%v,%d) error(%v)", oids, sType, err)
|
||
|
}
|
||
|
return
|
||
|
}
|