You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

346 lines
7.1 KiB
Go

package campaignnotice
import (
"joybuywork/internal/app"
"joybuywork/internal/consts/ckey"
"joybuywork/internal/plugins/jsonm"
"joybuywork/internal/repository/cache"
"joybuywork/internal/repository/dbcheck"
"joybuywork/internal/repository/model"
"joybuywork/internal/repository/mtype"
"joybuywork/internal/repository/withdefault"
"joybuywork/internal/service/queue/types"
"joybuywork/internal/utils/lockdo"
"joybuywork/internal/utils/logic"
"joybuywork/internal/utils/timez"
"time"
"gits.branchcn.com/backend/joybuywork/proto/go_proto/workerr"
"gits.branchcn.com/backend/microcode/plugins/derivative/lock"
"gorm.io/gen/field"
)
type GameAction struct {
logic.Logic
Req *types.GameAction
}
func (s *GameAction) Data() (data jsonm.JsonM) {
data, _ = jsonm.Marshal(s.Req)
return
}
func (s *GameAction) Exec() (err error) {
err = s.duration()
if err != nil {
return
}
err = s.total()
if err != nil {
return
}
err = s.date()
if err != nil {
return
}
return
}
// 入库
func (s *GameAction) duration() (err error) {
one := &model.GameAction{
ID: s.Req.ID,
ProjectID: s.Req.ProjectId,
GameID: s.Req.GameId,
UserID: s.Req.UserId,
LinkID: s.Req.LinkId,
Type: s.Req.Type,
ActionTime: s.Req.ActionTime,
Dimension: "",
}
one.SetDimension(&s.Req.Dimension)
m := s.Dao().GameAction
err = m.WithContext(s.Ctx).Create(one)
if err != nil {
return
}
return
}
func (s *GameAction) total() (err error) {
id, err := s._getTotalId(0)
if err != nil {
return
}
m := s.GetDao().GameTotal
var up []field.AssignExpr
switch s.Req.Type {
case mtype.GameActionTypeVisit:
var first bool
first, err = s._firstVisit(0)
if err != nil {
return
}
up = append(up, m.Pv.Add(1))
if first {
up = append(up, m.Uv.Add(1))
}
case mtype.GameActionTypeStay:
up = append(up, m.Psec.Add(int64(s.Req.Dimension.StaySec)))
}
if len(up) > 0 {
_, err = m.WithContext(s.Ctx).Where(m.ID.Eq(id)).UpdateSimple(up...)
if err != nil {
err = s.BE().MysqlError(err)
return
}
}
ltId, err := s._getTotalId(s.Req.LinkId)
if err != nil {
return
}
var ltUp []field.AssignExpr
switch s.Req.Type {
case mtype.GameActionTypeVisit:
var first bool
first, err = s._firstVisit(s.Req.LinkId)
if err != nil {
return
}
ltUp = append(ltUp, m.Pv.Add(1))
if first {
ltUp = append(ltUp, m.Uv.Add(1))
}
case mtype.GameActionTypeStay:
ltUp = append(ltUp, m.Psec.Add(int64(s.Req.Dimension.StaySec)))
}
if len(ltUp) > 0 {
_, err = m.WithContext(s.Ctx).Where(m.ID.Eq(ltId)).UpdateSimple(ltUp...)
if err != nil {
err = s.BE().MysqlError(err)
return
}
}
return
}
func (s *GameAction) _firstVisit(linkId int64) (first bool, err error) {
key := ckey.GameActionFirst(s.Req.ProjectId, s.Req.GameId, linkId, s.Req.UserId, mtype.GameActionTypeVisit)
if !app.Redis.Cache.SetNX(s.Ctx, key, 1, lockdo.Rand2HourExp()).Val() {
return
}
m := s.Dao().GameAction
visit, err := m.WithContext(s.Ctx).Where(
m.ProjectID.Eq(s.Req.ProjectId),
m.GameID.Eq(s.Req.GameId),
m.LinkID.Eq(linkId),
m.UserID.Eq(s.Req.UserId),
m.Type.Eq(mtype.GameActionTypeVisit),
).First()
if err = dbcheck.DbError(err); err != nil {
err = s.BE().MysqlError(err)
return
}
if visit == nil || visit.ID == s.Req.ID {
return true, nil
}
return
}
func (s *GameAction) date() (err error) {
day, start, end := timez.GMTStartAndEndTs(8)
id, err := s._getTotalDateId(0, day)
if err != nil {
return
}
m := s.GetDao().GameTotalDate
var up []field.AssignExpr
switch s.Req.Type {
case mtype.GameActionTypeVisit:
var first bool
first, err = s._firstDateVisit(0, day, start, end)
if err != nil {
return
}
up = append(up, m.Pv.Add(1))
if first {
up = append(up, m.Uv.Add(1))
}
case mtype.GameActionTypeStay:
up = append(up, m.Psec.Add(int64(s.Req.Dimension.StaySec)))
}
if len(up) > 0 {
_, err = m.WithContext(s.Ctx).Where(m.ID.Eq(id)).UpdateSimple(up...)
if err != nil {
err = s.BE().MysqlError(err)
return
}
}
ltId, err := s._getTotalDateId(s.Req.LinkId, day)
if err != nil {
return
}
var ltUp []field.AssignExpr
switch s.Req.Type {
case mtype.GameActionTypeVisit:
var first bool
first, err = s._firstDateVisit(s.Req.LinkId, day, start, end)
if err != nil {
return
}
ltUp = append(ltUp, m.Pv.Add(1))
if first {
ltUp = append(ltUp, m.Uv.Add(1))
}
case mtype.GameActionTypeStay:
ltUp = append(ltUp, m.Psec.Add(int64(s.Req.Dimension.StaySec)))
}
if len(ltUp) > 0 {
_, err = m.WithContext(s.Ctx).Where(m.ID.Eq(ltId)).UpdateSimple(ltUp...)
if err != nil {
err = s.BE().MysqlError(err)
return
}
}
return
}
func (s *GameAction) _firstDateVisit(linkId int64, day string, start, end int64) (first bool, err error) {
key := ckey.GameActionFirstDate(s.Req.ProjectId, s.Req.GameId, linkId, s.Req.UserId, mtype.GameActionTypeVisit, day)
if !app.Redis.Cache.SetNX(s.Ctx, key, 1, lockdo.Rand2HourExp()).Val() {
return
}
m := s.Dao().GameAction
visit, err := m.WithContext(s.Ctx).Where(
m.ProjectID.Eq(s.Req.ProjectId),
m.GameID.Eq(s.Req.GameId),
m.LinkID.Eq(linkId),
m.UserID.Eq(s.Req.UserId),
m.Type.Eq(mtype.GameActionTypeVisit),
m.ActionTime.Between(start, end),
).First()
if err = dbcheck.DbError(err); err != nil {
err = s.BE().MysqlError(err)
return
}
if visit == nil || visit.ID == s.Req.ID {
return true, nil
}
return
}
func (s *GameAction) _getTotalId(linkId int64) (id int64, err error) {
cc := cache.NewGameTotal(s.Ctx)
id, err = cc.FindByUniqIdx(s.Req.ProjectId, s.Req.GameId, linkId)
if err != nil {
err = s.BE().CacheError(err)
return
}
lc := app.NewFollower(s.Ctx, ckey.GameTotalCreateOnce(s.Req.ProjectId, s.Req.GameId, linkId), lock.SetExpire(10*time.Second)).Lock()
defer lc.Release()
if lc.Error() != nil {
err = workerr.BusyError
return
}
id, err = cc.FindByUniqIdx(s.Req.ProjectId, s.Req.GameId, linkId)
if err != nil {
err = s.BE().CacheError(err)
return
}
if id != 0 {
return
}
total := withdefault.GameTotal(&model.GameTotal{
ProjectID: s.Req.ProjectId,
GameID: s.Req.GameId,
LinkID: linkId,
})
err = s.GetDao().GameTotal.WithContext(s.Ctx).Create(total)
if err != nil {
err = s.BE().MysqlError(err)
return
}
return total.ID, nil
}
func (s *GameAction) _getTotalDateId(linkId int64, day string) (id int64, err error) {
cc := cache.NewGameTotalDate(s.Ctx)
id, err = cc.FindByUniqIdx(s.Req.ProjectId, s.Req.GameId, linkId, day)
if err != nil {
err = s.BE().CacheError(err)
return
}
lc := app.NewFollower(s.Ctx, ckey.GameTotalCreateOnceDate(s.Req.ProjectId, s.Req.GameId, linkId, day), lock.SetExpire(10*time.Second)).Lock()
defer lc.Release()
if lc.Error() != nil {
err = workerr.BusyError
return
}
id, err = cc.FindByUniqIdx(s.Req.ProjectId, s.Req.GameId, linkId, day)
if err != nil {
err = s.BE().CacheError(err)
return
}
if id != 0 {
return
}
total := withdefault.GameTotalDate(&model.GameTotalDate{
ProjectID: s.Req.ProjectId,
GameID: s.Req.GameId,
LinkID: linkId,
Ymd: day,
})
err = s.GetDao().GameTotalDate.WithContext(s.Ctx).Create(total)
if err != nil {
err = s.BE().MysqlError(err)
return
}
return total.ID, nil
}