package task import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/redis/redis_key" "code.gitea.io/gitea/modules/redis/redis_lock" "code.gitea.io/gitea/services/reward" "errors" "time" ) func Accomplish(userId int64, taskType models.TaskType, sourceId string) { go accomplish(userId, taskType, sourceId) } func accomplish(userId int64, taskType models.TaskType, sourceId string) error { //lock var taskLock = redis_lock.NewDistributeLock(redis_key.TaskAccomplishLock(userId, sourceId, taskType)) if !taskLock.Lock(3 * time.Second) { log.Info("duplicated task request,userId=%d taskType=%s sourceId=%s", userId, taskType, sourceId) return nil } defer taskLock.UnLock() //is handled before? isHandled, err := isHandled(taskType, sourceId) if err != nil { log.Error("Get isHandled error,%v", err) return err } if isHandled { log.Info("task has been handled,userId=%d taskType=%s sourceId=%s", userId, taskType, sourceId) return nil } //get task config config, err := GetTaskConfig(taskType) if err != nil { log.Error("GetTaskConfig error,%v", err) return err } if config == nil { log.Info("task config not exist,userId=%d taskType=%s sourceId=%s", userId, taskType, sourceId) return nil } //is limited? isLimited, err := IsLimited(userId, config) if err != nil { log.Error("get limited error,%v", err) return err } if isLimited { log.Info("task accomplish maximum times are reached,userId=%d taskType=%s sourceId=%s", userId, taskType, sourceId) return nil } //add log models.InsertTaskAccomplishLog(&models.TaskAccomplishLog{ ConfigId: config.ID, TaskCode: config.TaskCode, UserId: userId, SourceId: sourceId, }) //reward reward.Send(reward.RewardOperateContext{ SourceType: models.SourceTypeAccomplishTask, SourceId: sourceId, Reward: reward.Reward{ Amount: config.AwardAmount, Type: config.AwardType, }, TargetUserId: userId, }) return nil } func isHandled(taskType models.TaskType, sourceId string) (bool, error) { _, err := models.GetTaskAccomplishLogBySourceIdAndTaskCode(sourceId, taskType.String()) if err != nil { if models.IsErrRecordNotExist(err) { return false, nil } return false, err } return true, nil } func IsLimited(userId int64, config *models.TaskConfig) (bool, error) { limiter := GetLimiter(config.RefreshRate) if limiter == nil { return false, errors.New("task config incorrect") } n, err := models.CountOnceTask(config.ID, userId, limiter.GetCurrentPeriod()) if err != nil { return false, err } return n >= config.Times, nil }