|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- 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/modules/util"
- "code.gitea.io/gitea/services/reward"
- "code.gitea.io/gitea/services/reward/limiter"
- "fmt"
- "time"
- )
-
- func Accomplish(userId int64, taskType string, sourceId string) {
- go accomplish(userId, taskType, sourceId)
- }
-
- func accomplish(userId int64, taskType string, sourceId string) error {
- defer func() {
- if err := recover(); err != nil {
- combinedErr := fmt.Errorf("%s\n%s", err, log.Stack(2))
- log.Error("PANIC:%v", combinedErr)
- }
- }()
- //lock
- var taskLock = redis_lock.NewDistributeLock(redis_key.TaskAccomplishLock(sourceId, taskType))
- isOk, err := taskLock.Lock(3 * time.Second)
- if err != nil {
- log.Error("get taskLock error. %v", err)
- return err
- }
- if !isOk {
- 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?
- if isLimited(userId, config) {
- log.Info("task accomplish maximum times are reached,userId=%d taskType=%s sourceId=%s", userId, taskType, sourceId)
- return nil
- }
-
- //add log
- logId := util.UUID()
- _, err = models.InsertTaskAccomplishLog(&models.TaskAccomplishLog{
- LogId: logId,
- ConfigId: config.ID,
- TaskCode: config.TaskCode,
- UserId: userId,
- SourceId: sourceId,
- })
- if err != nil {
- return err
- }
-
- //reward
- reward.Send(models.RewardOperateContext{
- SourceType: models.SourceTypeAccomplishTask,
- SourceId: logId,
- Reward: models.Reward{
- Amount: config.AwardAmount,
- Type: config.AwardType,
- },
- TargetUserId: userId,
- RequestId: logId,
- OperateType: models.OperateTypeIncrease,
- })
-
- return nil
- }
-
- func isHandled(taskType string, sourceId string) (bool, error) {
- _, err := models.GetTaskAccomplishLogBySourceIdAndTaskCode(sourceId, taskType)
- if err != nil {
- if models.IsErrRecordNotExist(err) {
- return false, nil
- }
- return false, err
- }
- return true, nil
-
- }
-
- func isLimited(userId int64, config *models.TaskConfig) bool {
- if err := limiter.CheckLimit(config.TaskCode, models.LimitTypeTask, userId, 1); err != nil {
- return true
- }
- return false
-
- }
|