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.
138 lines
3.4 KiB
138 lines
3.4 KiB
package service |
|
|
|
import ( |
|
"context" |
|
"sync" |
|
"time" |
|
|
|
"go-common/app/job/main/reply-feed/model" |
|
"go-common/library/cache/redis" |
|
"go-common/library/log" |
|
) |
|
|
|
// func (s *Service) delZSet(ctx context.Context, oid int64, tp int) (err error) { |
|
// var names []string |
|
// s.algorithmsLock.RLock() |
|
// for _, algorithm := range s.algorithms { |
|
// names = append(names, algorithm.Name()) |
|
// } |
|
// s.algorithmsLock.RUnlock() |
|
// if err = s.dao.DelReplyZSetRds(ctx, names, oid, tp); err != nil { |
|
// log.Error("Del ZSet from redis oid(%d) type(%d) error(%v)", oid, tp, err) |
|
// } |
|
// return |
|
// } |
|
|
|
func (s *Service) remZSet(ctx context.Context, oid int64, tp int, rpID int64) (err error) { |
|
var ( |
|
names []string |
|
) |
|
s.algorithmsLock.RLock() |
|
for _, algorithm := range s.algorithms { |
|
names = append(names, algorithm.Name()) |
|
} |
|
s.algorithmsLock.RUnlock() |
|
for _, name := range names { |
|
if err = s.dao.RemReplyZSetRds(ctx, name, oid, tp, rpID); err != nil { |
|
log.Error("Remove reply (name: %s, oid: %d, type: %d, rpID: %d) from ZSet failed.", name, oid, tp, rpID) |
|
return |
|
} |
|
} |
|
return |
|
} |
|
|
|
func (s *Service) upsertZSet(ctx context.Context, oid int64, tp int) { |
|
var ( |
|
rpIDs []int64 |
|
rs []*model.ReplyStat |
|
err error |
|
ts int64 |
|
) |
|
// 获取计时器 |
|
if ts, err = s.dao.CheckerTsRds(ctx, oid, tp); err != nil && err != redis.ErrNil { |
|
// 出错不刷新,如果缓存里还没有的话刷新 |
|
return |
|
} else if time.Now().Unix()-ts < s.c.RefreshTime { |
|
// 小于CD时间不刷新 |
|
return |
|
} |
|
// 从reply set中取rpIDs |
|
ok, err := s.dao.ExpireReplySetRds(ctx, oid, tp) |
|
if err != nil { |
|
return |
|
} |
|
if ok { |
|
// 缓存有则从redis中取 |
|
if rpIDs, err = s.dao.ReplySetRds(ctx, oid, tp); err != nil { |
|
return |
|
} |
|
} else { |
|
// 缓存中没有从DB中取 |
|
if rpIDs, err = s.dao.RpIDs(ctx, oid, tp); err != nil { |
|
return |
|
} |
|
// 异步回源 |
|
s.taskQ.Do(ctx, func(ctx context.Context) { |
|
s.setReplySetBatch(ctx, oid, tp) |
|
}) |
|
} |
|
// 从MC中获取reply stat |
|
if rs, err = s.GetStatsByID(ctx, oid, tp, rpIDs); err != nil { |
|
return |
|
} |
|
// 重新计算分值 |
|
rsMap, err := s.recalculateScore(ctx, rs) |
|
if err != nil { |
|
return |
|
} |
|
for name, rs := range rsMap { |
|
name, rs := name, rs |
|
s.replyListQ.Do(ctx, func(ctx context.Context) { |
|
s.dao.SetReplyZSetRds(ctx, name, oid, tp, rs) |
|
}) |
|
} |
|
// 更新完后更新计时器 |
|
if err = s.dao.SetCheckerTsRds(ctx, oid, tp); err != nil { |
|
log.Error("set refresh checker error (%v)", err) |
|
} |
|
} |
|
|
|
// recalculateScore recalculate all e group reply list score. |
|
func (s *Service) recalculateScore(ctx context.Context, stats []*model.ReplyStat) (rsMap map[string][]*model.ReplyScore, err error) { |
|
rsMap = make(map[string][]*model.ReplyScore) |
|
s.algorithmsLock.RLock() |
|
defer s.algorithmsLock.RUnlock() |
|
for _, algorithm := range s.algorithms { |
|
wg := sync.WaitGroup{} |
|
rs := make([]*model.ReplyScore, len(stats)) |
|
for i := range stats { |
|
j := i |
|
wg.Add(1) |
|
s.calculator.JobQueue <- func() { |
|
rs[j] = algorithm.Score(stats[j]) |
|
wg.Done() |
|
} |
|
} |
|
wg.Wait() |
|
rsMap[algorithm.Name()] = rs |
|
} |
|
return |
|
} |
|
|
|
func (s *Service) isHot(ctx context.Context, name string, oid, rpID int64, tp int) (isHot bool, err error) { |
|
rpIDs, err := s.dao.RangeReplyZSetRds(ctx, name, oid, tp, 0, 5) |
|
if err != nil || len(rpIDs) <= 0 { |
|
return |
|
} |
|
rs, err := s.GetStatsByID(ctx, oid, tp, rpIDs) |
|
if err != nil { |
|
return |
|
} |
|
for _, r := range rs { |
|
if r.RpID == rpID && r.Like >= 3 { |
|
isHot = true |
|
return |
|
} |
|
} |
|
return |
|
}
|
|
|