package task_m import ( "git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/utils" "gorm.io/gorm" "hilo-group/_const/enum/task_e" "hilo-group/myerr" "hilo-group/myerr/bizerr" "strconv" "time" ) type TaskConfig struct { mysql.Entity *domain.Model `gorm:"-"` Name mysql.Str Diamond mysql.Num //任务类型 Type task_e.TypeTaskConfig //频率类型 RateType task_e.RateTypeTaskConfig //完成次数 FinishN mysql.Num //排序 I mysql.Num //奖励次数 AwardN mysql.Num Status mysql.UserYesNo } type TaskUser struct { mysql.Entity *domain.Model `gorm:"-"` TaskConfigId mysql.ID UserId mysql.ID DayStr mysql.Str HasFinish mysql.YesNo HasAward mysql.YesNo //整个完成奖励了 AwardN mysql.Num //获取奖励次数 FinishN mysql.Num } type TaskUserDetail struct { mysql.Entity *domain.Model `gorm:"-"` TaskConfigId mysql.ID UserId mysql.ID TaskUserId mysql.ID OriginId mysql.ID } func addTaskUserDetail(model *domain.Model, taskConfigId mysql.ID, userId mysql.ID, taskUserId mysql.ID, originId mysql.ID) error { taskUserDetail := &TaskUserDetail{ Model: model, TaskConfigId: taskConfigId, UserId: userId, TaskUserId: taskUserId, OriginId: originId, } return taskUserDetail.Persistent() } func GetTaskUserOrErr(model *domain.Model, userId uint64, taskConfigId uint64) (*TaskUser, TaskConfig, error) { //获取任务配置 taskConfig := TaskConfig{} if err := model.Db.Model(&TaskConfig{}).Where(&TaskConfig{ Status: mysql.USER, }).First(&taskConfig, taskConfigId).Error; err != nil { return nil, TaskConfig{}, myerr.WrapErr(err) } // paramTaskUser := TaskUser{ TaskConfigId: taskConfig.ID, UserId: userId, } if taskConfig.RateType == task_e.Daily { paramTaskUser.DayStr = time.Now().Format(utils.COMPACT_DATE_FORMAT) } // taskUser := TaskUser{} if err := model.Db.Model(&TaskUser{}).Where(¶mTaskUser).First(&taskUser).Error; err != nil { return nil, TaskConfig{}, myerr.WrapErr(err) } taskUser.Model = model // return &taskUser, taskConfig, nil } func getTaskUserOrInit(model *domain.Model, userId uint64, taskConfig TaskConfig) (*TaskUser, error) { //获取任务用户 taskUser := TaskUser{} paramTaskUser := TaskUser{ TaskConfigId: taskConfig.ID, UserId: userId, } if taskConfig.RateType == task_e.Daily { paramTaskUser.DayStr = time.Now().Format(utils.COMPACT_DATE_FORMAT) } if err := model.Db.Model(&TaskUser{}).Where(¶mTaskUser).First(&taskUser).Error; err != nil { if err == gorm.ErrRecordNotFound { return &TaskUser{ Model: model, TaskConfigId: taskConfig.ID, UserId: userId, DayStr: paramTaskUser.DayStr, HasFinish: mysql.NO, HasAward: mysql.NO, FinishN: 0, }, nil } else { return nil, myerr.WrapErr(err) } } taskUser.Model = model return &taskUser, nil } // 次数加1 func (taskUser *TaskUser) addFinishN(taskConfig TaskConfig) bool { //没有使用sql悲观锁,update set where,第一:观察业务,都是用户自动触发,有时间性 第二:验证业务这样写,被投诉的概率,以证明此场景业务。 if taskUser.HasFinish == mysql.YES { return false } else { taskUser.FinishN = taskUser.FinishN + 1 if taskUser.FinishN >= taskConfig.FinishN { taskUser.HasFinish = mysql.YES } return true } } // 次数覆盖 func (taskUser *TaskUser) beFinishN(taskConfig TaskConfig, finishN uint32) bool { //没有使用sql悲观锁,update set where,第一:观察业务,都是用户自动触发,有时间性 第二:验证业务这样写,被投诉的概率,以证明此场景业务。 if taskUser.HasFinish == mysql.YES { return false } else { taskUser.FinishN = finishN if taskUser.FinishN >= taskConfig.FinishN { taskUser.HasFinish = mysql.YES } return true } } func (taskUser *TaskUser) Award(taskConfig TaskConfig) error { if taskUser.HasAward == mysql.YES { return bizerr.TaskHasAward } taskUser.AwardN = taskUser.AwardN + 1 if taskUser.AwardN >= taskConfig.AwardN { taskUser.HasAward = mysql.YES } taskUser.SetCheckUpdateCondition("has_award = " + strconv.Itoa(int(mysql.NO))) return nil } func AddTaskUser(model *domain.Model, t task_e.TypeTaskConfig, userId uint64, orginId uint64) (mysql.ID, error) { //获取任务配置 taskConfig := TaskConfig{} if err := model.Db.Model(&TaskConfig{}).Where(&TaskConfig{ Type: t, Status: mysql.USER, }).First(&taskConfig).Error; err != nil { return 0, myerr.WrapErr(err) } // taskUser, err := getTaskUserOrInit(model, userId, taskConfig) if err != nil { return 0, err } if taskUser.addFinishN(taskConfig) { if err := taskUser.Persistent(); err != nil { return 0, myerr.WrapErr(err) } return taskConfig.ID, addTaskUserDetail(taskUser.Model, taskConfig.ID, userId, taskUser.ID, orginId) } return taskConfig.ID, nil } // return true:已经完成 false:未完成 func isTaskUserFinish(model *domain.Model, t task_e.TypeTaskConfig, userId uint64) (bool, error) { //获取任务配置 taskConfig := TaskConfig{} if err := model.Db.Model(&TaskConfig{}).Where(&TaskConfig{ Type: t, Status: mysql.USER, }).First(&taskConfig).Error; err != nil { return false, myerr.WrapErr(err) } // taskUser, err := getTaskUserOrInit(model, userId, taskConfig) if err != nil { return false, err } return taskUser.HasFinish == mysql.YES, nil } func addTaskUserFinishN(model *domain.Model, t task_e.TypeTaskConfig, userId uint64, finishN uint32) error { //获取任务配置 taskConfig := TaskConfig{} if err := model.Db.Model(&TaskConfig{}).Where(&TaskConfig{ Type: t, Status: mysql.USER, }).First(&taskConfig).Error; err != nil { return myerr.WrapErr(err) } // taskUser, err := getTaskUserOrInit(model, userId, taskConfig) if err != nil { return err } if taskUser.beFinishN(taskConfig, finishN) { if err := taskUser.Persistent(); err != nil { return myerr.WrapErr(err) } return addTaskUserDetail(taskUser.Model, taskConfig.ID, userId, taskUser.ID, 0) } return nil }