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 }