bilibili-backup/app/job/main/click/service/click.go
2019-04-22 02:59:20 +00:00

202 lines
5.6 KiB
Go

package service
import (
"context"
"strings"
"sync/atomic"
"time"
"go-common/app/job/main/click/model"
"go-common/library/log"
)
func (s *Service) isAllow(ctx context.Context, c *model.ClickMsg) (rtype int8, err error) {
var (
f *model.Forbid
ok bool
duration int64
)
rtype = model.LogTypeForNotUse
// 自动播放的恶心逻辑 开始
if c.Plat == model.PlatForAutoPlayAndroid || c.Plat == model.PlatForAutoPlayInlineAndroid || c.Plat == model.PlatForAutoPlayIOS || c.Plat == model.PlafForAutoPlayInlineIOS ||
strings.Contains(c.UserAgent, "(inline_play_begin)") { // plat的逻辑更换为UA中添加(inline_play_begin)
log.Warn("no count! hit autoplay plat(%d) aid(%d)", c.Plat, c.AID)
rtype = model.LogTypeForInlineBegin // 2
if c.Buvid != "" {
if err = s.setRealDid(ctx, c.Buvid, c.AID, c.Did); err != nil {
log.Error("s.setRealDid(%s, %s) error(%v)", c.Buvid, c.Did, err)
return
}
}
return
}
// 自动播放的恶心逻辑 结束
if c.MID > 0 {
if _, ok := s.forbidMids[c.MID]; ok {
log.Warn("mid(%d) forbidden", c.MID)
return
}
}
if f, ok = s.forbids[c.AID][c.Plat]; ok {
if f.Lv == -2 && (strings.HasSuffix(c.UserAgent, "(no_accesskey)") || c.MID == 0) {
log.Warn("no count! hit no_accesskey! agent(%s) aid(%d) mid(%d) plat(%d)", c.UserAgent, c.AID, c.MID, c.Plat)
return
} else if f.Lv == -1 && c.MID == 0 {
// 游客不计算点击数
log.Warn("no count! hit forbid_lv(%d) mid(%d)", f.Lv, c.MID)
return
} else if f.Lv >= 0 && (c.Lv <= f.Lv || c.MID == 0) {
// 游客和低于锁定等级的不计算点击数
return
}
}
if c.EpID > 0 {
if err = s.checkEpAvRelation(ctx, c.AID, c.EpID, c.SeasonType); err != nil {
log.Error("s.getOid(%d, %d, %d) error(%v)", c.AID, c.EpID, c.SeasonType)
return
}
}
if !s.canCount(ctx, c.AID, c.EpID, c.IP, c.STime, c.Did) {
log.Warn("same ip(%s) and av(%d) replay", c.IP, c.AID)
return
}
duration = s.ArcDuration(ctx, c.AID)
if s.isReplay(ctx, c.MID, c.AID, c.Did, duration) {
log.Warn("mid(%d) bvid(%s) aid(%d) epid(%d) isPGC(%v) gapTime(%d) is replay", c.MID, c.Did, c.AID, c.EpID, c.EpID > 0, duration)
return
}
rtype = model.LogTypeForTurly // 1
return
}
func (s *Service) checkEpAvRelation(ctx context.Context, aid, epid int64, seasonType int) (err error) {
s.etamMutex.RLock()
_, ok := s.eTam[epid]
s.etamMutex.RUnlock()
if ok {
return
}
var isLegal bool
if isLegal, err = s.db.IsLegal(ctx, aid, epid, seasonType); err != nil {
// 接口请求失败时按ugc维度走
err = nil
} else if !isLegal {
// epid not exist
log.Error("aid(%d) epid(%d) type(%d) not exist", aid, epid, seasonType)
return
}
s.etamMutex.Lock()
s.eTam[epid] = aid
s.etamMutex.Unlock()
return
}
// 播放计数主方法
func (s *Service) countClick(ctx context.Context, msg *model.ClickMsg, i int64) (err error) {
var (
ci *model.ClickInfo
ok bool
now = time.Now().Unix()
)
if msg == nil {
log.Info("svr close s.aidMap length is %d", len(s.aidMap[i]))
for _, ci = range s.aidMap[i] {
// 反正这些视频点击数很多,不差这些,照顾小透明
if ci.GetSum() > 100 {
continue
}
s.upClick(ctx, ci)
}
return
}
idx := msg.AID % s.c.ChanNum
if atomic.LoadInt64(&s.lockedMap[idx]) == _locked {
log.Info("locking aidMap[%d] current length(%d)", idx, len(s.aidMap[idx]))
for _, ci := range s.aidMap[idx] {
if ci.GetSum() > 100 {
continue
}
s.upClick(ctx, ci)
delete(s.aidMap[idx], ci.Aid)
time.Sleep(1 * time.Millisecond)
}
atomic.StoreInt64(&s.lockedMap[idx], _unLock)
log.Info("unlocked aidMap[%d] current length(%d)", idx, len(s.aidMap[idx]))
}
if ci, ok = s.aidMap[idx][msg.AID]; !ok {
if ci, err = s.db.Click(ctx, msg.AID); err != nil {
log.Error("s.db.Click(%d) error(%v)", msg.AID, err)
return
}
if ci == nil {
if _, err = s.db.AddClick(ctx, msg.AID, 0, 0, 0, 0, 0, 0); err != nil {
log.Error("s.db.AddClick(%d) error(%v)", msg.AID, err)
return
}
ci = &model.ClickInfo{Aid: msg.AID}
}
ci.Ready(now)
s.aidMap[idx][msg.AID] = ci
}
switch msg.Plat {
case 0:
ci.Web++
case 1:
ci.H5++
case 2:
ci.Outer++
case 3:
ci.Ios++
case 4:
ci.Android++
case 5:
ci.AndroidTV++
}
if ci.Sum == 0 || now-ci.LastChangeTime > s.c.LastChangeTime {
if err = s.upClick(ctx, ci); err != nil {
log.Error("s.upClick(%v) error(%v)", ci, err)
return
}
log.Info("truly add click message(%+v)", msg)
if now-ci.LastChangeTime > s.c.ReleaseTime || ci.Aid == s.c.BnjMainAid || ci.NeedRelease() {
delete(s.aidMap[idx], msg.AID)
return
}
ci.Ready(now)
}
return
}
func (s *Service) upClick(c context.Context, ci *model.ClickInfo) (err error) {
if _, err = s.db.UpClick(c, ci); err != nil {
log.Error("s.db.UpClick(%+v) error(%v)", ci, err)
return
}
s.busChan <- &model.StatMsg{AID: ci.Aid, Click: int(ci.Sum + ci.GetSum())}
// 拜年祭需求 单品视频的播放数算进主视频
if _, ok := s.bnjListAidMap[ci.Aid]; ok {
bnj := &model.ClickInfo{
Aid: s.c.BnjMainAid,
Web: ci.Web,
H5: ci.H5,
Outer: ci.Outer,
Ios: ci.Ios,
Android: ci.Android,
AndroidTV: ci.AndroidTV,
}
if _, err = s.db.UpClick(c, bnj); err != nil {
log.Error("s.db.UpClick(%d) error(%v)", s.c.BnjMainAid, err)
return
}
log.Info("bnjaid(%d) Forced to increase click(%v) by relateAid(%d)", s.c.BnjMainAid, bnj, ci.Aid)
}
// 拜年祭需求 单品视频的播放数算进主视频
return
}
// SetSpecial http set special aid click
func (s *Service) SetSpecial(c context.Context, aid, num int64, tp string) (err error) {
_, err = s.db.UpSpecial(c, aid, tp, num)
return
}