From c01c97bba14d22d4bb06784abb6bf190d3511a68 Mon Sep 17 00:00:00 2001 From: chenyifan01 Date: Wed, 6 Jul 2022 16:57:35 +0800 Subject: [PATCH] #2225 update --- models/limit_config.go | 5 +- models/task_config.go | 136 ++++++++++++++++++++++++++---- modules/redis/redis_key/task_redis_key.go | 3 + routers/reward/point/point.go | 4 +- routers/task/config.go | 4 +- services/reward/limiter/limiter.go | 4 +- services/task/task_config.go | 112 +++++++++++++++--------- 7 files changed, 203 insertions(+), 65 deletions(-) diff --git a/models/limit_config.go b/models/limit_config.go index 5b0adc5a2..284edec6f 100644 --- a/models/limit_config.go +++ b/models/limit_config.go @@ -57,6 +57,7 @@ type LimitConfig struct { LimitNum int64 `xorm:"NOT NULL"` LimitCode string LimitType string `xorm:"NOT NULL"` + RelatedId int64 `xorm:"INDEX"` CreatorId int64 `xorm:"NOT NULL"` CreatorName string DeleterId int64 @@ -102,9 +103,9 @@ func GetLimitConfigByLimitType(limitType LimitType) ([]LimitConfig, error) { return r, nil } -func GetLimitersByLimitTypeWithDeleted(limitType LimitType) ([]LimitConfig, error) { +func GetLimitersByRelatedIdWithDeleted(limitType LimitType) ([]LimitConfig, error) { r := make([]LimitConfig, 0) - err := x.Unscoped().Where(" limit_type = ?", limitType.Name()).Find(&r) + err := x.Unscoped().Where(" = ?", limitType.Name()).Find(&r) if err != nil { return nil, err } else if len(r) == 0 { diff --git a/models/task_config.go b/models/task_config.go index fd8648296..0f7638795 100644 --- a/models/task_config.go +++ b/models/task_config.go @@ -21,10 +21,13 @@ type TaskConfig struct { CreatorName string CreatedUnix timeutil.TimeStamp `xorm:"created"` DeletedAt timeutil.TimeStamp `xorm:"deleted"` + DeleterId int64 + DeleterName string } type TaskConfigWithLimit struct { - TaskCode string `binding:"Required;MaxSize(256)"` + ID int64 + TaskCode string Tittle string AwardType string AwardAmount int64 @@ -34,6 +37,36 @@ type TaskConfigWithLimit struct { DeleteAt timeutil.TimeStamp Limiters []*LimitConfigVO } + +type TaskConfigWithLimitResponse struct { + Records []*TaskConfigWithSingleLimit + Total int64 + PageSize int + Page int +} + +type TaskConfigWithSingleLimit struct { + ID int64 + TaskCode string + AwardType string + AwardAmount int64 + Creator string + IsDeleted bool + CreatedUnix timeutil.TimeStamp + DeleteAt timeutil.TimeStamp + RefreshRate string + LimitNum int64 +} + +type TaskAndLimiterConfig struct { + TaskConfig TaskConfig `xorm:"extends"` + LimitConfig LimitConfig `xorm:"extends"` +} + +func (TaskAndLimiterConfig) TableName() string { + return "task_config" +} + type BatchLimitConfigVO struct { ConfigList []TaskConfigWithLimit } @@ -54,6 +87,14 @@ func GetTaskConfigByTaskCode(taskCode string) (*TaskConfig, error) { } return getTaskConfig(t) } + +func GetTaskConfigByID(id int64) (*TaskConfig, error) { + t := &TaskConfig{ + ID: id, + } + return getTaskConfig(t) +} + func GetTaskConfigList() ([]*TaskConfig, error) { r := make([]*TaskConfig, 0) err := x.Find(&r) @@ -65,34 +106,40 @@ func GetTaskConfigList() ([]*TaskConfig, error) { } return r, nil } -func GetTaskConfigPageWithDeleted(opt ListOptions) ([]*TaskConfig, error) { +func GetTaskConfigPageWithDeleted(opt ListOptions) ([]*TaskAndLimiterConfig, int64, error) { if opt.Page <= 0 { opt.Page = 1 } - r := make([]*TaskConfig, 0) - err := x.Unscoped().Limit(opt.PageSize, (opt.Page-1)*opt.PageSize).OrderBy("deleted_at desc,id desc").Find(&r) + n, err := x.Unscoped().Count(&TaskConfig{}) if err != nil { - return nil, err + return nil, 0, err } + r := make([]*TaskAndLimiterConfig, 0) + err = x.Join("LEFT", "limit_config", "task_config.id = limit_config.related_id").Unscoped().Limit(opt.PageSize, (opt.Page-1)*opt.PageSize).OrderBy("task_config.deleted_at desc,task_config.id desc").Find(&r) + if len(r) == 0 { - return nil, ErrRecordNotExist{} + return nil, 0, ErrRecordNotExist{} } - return r, nil + return r, n, nil } -func AddTaskConfig(config TaskConfigWithLimit, doer *User) error { +func EditTaskConfig(config TaskConfigWithLimit, doer *User) error { sess := x.NewSession() defer sess.Close() //delete old task config p := &TaskConfig{ - TaskCode: config.TaskCode, + ID: config.ID, } _, err := sess.Delete(p) if err != nil { sess.Rollback() return err } + //update deleter + p.DeleterId = doer.ID + p.DeleterName = doer.Name + sess.Where("id = ?", config.ID).Unscoped().Update(p) //add new config t := &TaskConfig{ @@ -103,7 +150,7 @@ func AddTaskConfig(config TaskConfigWithLimit, doer *User) error { CreatorId: doer.ID, CreatorName: doer.Name, } - _, err = sess.Insert(t) + _, err = sess.InsertOne(t) if err != nil { sess.Rollback() return err @@ -111,20 +158,69 @@ func AddTaskConfig(config TaskConfigWithLimit, doer *User) error { //delete old limiter config lp := &LimitConfig{ - LimitType: LimitTypeTask.Name(), - LimitCode: config.TaskCode, + RelatedId: config.ID, } _, err = sess.Delete(lp) if err != nil { sess.Rollback() return err } + lp.DeleterName = doer.Name + lp.DeleterId = doer.ID + //update deleter + sess.Where("related_id = ?", config.ID).Unscoped().Update(lp) + + //add new limiter config + if config.Limiters != nil && len(config.Limiters) > 0 { + for _, v := range config.Limiters { + //add new config + l := &LimitConfig{ + Tittle: v.Tittle, + RefreshRate: v.RefreshRate, + Scope: v.Scope, + LimitNum: v.LimitNum, + LimitCode: config.TaskCode, + LimitType: LimitTypeTask.Name(), + CreatorId: doer.ID, + CreatorName: doer.Name, + RelatedId: t.ID, + } + _, err = sess.Insert(l) + if err != nil { + sess.Rollback() + return err + } + } + } + sess.Commit() + return nil +} + +func NewTaskConfig(config TaskConfigWithLimit, doer *User) error { + sess := x.NewSession() + defer sess.Close() + + //add new config + t := &TaskConfig{ + TaskCode: config.TaskCode, + Tittle: config.Tittle, + AwardType: config.AwardType, + AwardAmount: config.AwardAmount, + CreatorId: doer.ID, + CreatorName: doer.Name, + } + _, err := sess.InsertOne(t) + if err != nil { + sess.Rollback() + return err + } //add new limiter config if config.Limiters != nil && len(config.Limiters) > 0 { for _, v := range config.Limiters { //add new config l := &LimitConfig{ + RelatedId: t.ID, Tittle: v.Tittle, RefreshRate: v.RefreshRate, Scope: v.Scope, @@ -145,30 +241,36 @@ func AddTaskConfig(config TaskConfigWithLimit, doer *User) error { return nil } -func DelTaskConfig(taskCode string) error { +func DelTaskConfig(id int64, doer *User) error { sess := x.NewSession() defer sess.Close() //delete old task config p := &TaskConfig{ - TaskCode: taskCode, + ID: id, } _, err := sess.Delete(p) if err != nil { sess.Rollback() return err } - + //update deleter + p.DeleterId = doer.ID + p.DeleterName = doer.Name + sess.Where("id = ?", id).Unscoped().Update(p) //delete old limiter config lp := &LimitConfig{ - LimitType: LimitTypeTask.Name(), - LimitCode: taskCode, + RelatedId: id, } _, err = sess.Delete(lp) if err != nil { sess.Rollback() return err } + lp.DeleterName = doer.Name + lp.DeleterId = doer.ID + //update deleter + sess.Where("related_id = ?", id).Unscoped().Update(lp) sess.Commit() return nil } diff --git a/modules/redis/redis_key/task_redis_key.go b/modules/redis/redis_key/task_redis_key.go index 4e30688e1..64c54ec06 100644 --- a/modules/redis/redis_key/task_redis_key.go +++ b/modules/redis/redis_key/task_redis_key.go @@ -9,3 +9,6 @@ func TaskAccomplishLock(sourceId string, taskType string) string { func TaskConfigList() string { return KeyJoin(TASK_REDIS_PREFIX, "config", "list") } +func TaskConfigOperateLock(taskCode, rewardType string) string { + return KeyJoin(TASK_REDIS_PREFIX, "config", "operate", "lock") +} diff --git a/routers/reward/point/point.go b/routers/reward/point/point.go index 3828a2900..b628c4f70 100644 --- a/routers/reward/point/point.go +++ b/routers/reward/point/point.go @@ -35,8 +35,8 @@ func GetPointAccount(ctx *context.Context) { } func GetPointRecordList(ctx *context.Context) { - operateType := ctx.Query("operate") - page := ctx.QueryInt("page") + operateType := ctx.Query("Operate") + page := ctx.QueryInt("Page") var orderBy models.RewardOperateOrderBy switch ctx.Query("sort") { default: diff --git a/routers/task/config.go b/routers/task/config.go index 71f3c2a2b..4e52d70eb 100644 --- a/routers/task/config.go +++ b/routers/task/config.go @@ -11,7 +11,7 @@ import ( ) func GetTaskConfigList(ctx *context.Context) { - page := ctx.QueryInt("page") + page := ctx.QueryInt("Page") r, err := task.GetTaskConfigWithLimitList(models.ListOptions{PageSize: 20, Page: page}) if err != nil { ctx.JSON(http.StatusOK, response.ServerError(err.Error())) @@ -30,7 +30,7 @@ func OperateTaskConfig(ctx *context.Context, config models.TaskConfigWithLimit) case "new": err = task.AddTaskConfig(config, ctx.User) case "del": - err = task.DelTaskConfig(config.TaskCode) + err = task.DelTaskConfig(config.ID, ctx.User) default: err = errors.New("action type error") } diff --git a/services/reward/limiter/limiter.go b/services/reward/limiter/limiter.go index 88ce80c67..c303a1ef3 100644 --- a/services/reward/limiter/limiter.go +++ b/services/reward/limiter/limiter.go @@ -246,8 +246,8 @@ func GetLimitersByLimitType(limitType models.LimitType) ([]models.LimitConfig, e return limiters, nil } -func GetLimitersByLimitTypeWithDeleted(limitType models.LimitType) ([]models.LimitConfig, error) { - limiters, err := models.GetLimitersByLimitTypeWithDeleted(limitType) +func GetLimitersByRelatedIdWithDeleted(limitType models.LimitType) ([]models.LimitConfig, error) { + limiters, err := models.GetLimitersByRelatedIdWithDeleted(limitType) if err != nil { if models.IsErrRecordNotExist(err) { return nil, nil diff --git a/services/task/task_config.go b/services/task/task_config.go index 6aefc8ba1..0f470d763 100644 --- a/services/task/task_config.go +++ b/services/task/task_config.go @@ -5,7 +5,7 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/redis/redis_client" "code.gitea.io/gitea/modules/redis/redis_key" - "code.gitea.io/gitea/services/reward/limiter" + "code.gitea.io/gitea/modules/redis/redis_lock" "encoding/json" "errors" "time" @@ -52,58 +52,64 @@ func GetTaskConfigList() ([]*models.TaskConfig, error) { return config, nil } -func GetTaskConfigPageWithDeleted(opt models.ListOptions) ([]*models.TaskConfig, error) { - config, err := models.GetTaskConfigPageWithDeleted(opt) +func GetTaskConfigPageWithDeleted(opt models.ListOptions) ([]*models.TaskAndLimiterConfig, int64, error) { + config, count, err := models.GetTaskConfigPageWithDeleted(opt) if err != nil { log.Error(" GetTaskConfigPageWithDeleted from model error. %v", err) if models.IsErrRecordNotExist(err) { - return nil, nil + return nil, 0, nil } - return nil, err + return nil, 0, err } - return config, nil + return config, count, nil } -func GetTaskConfigWithLimitList(opt models.ListOptions) ([]*models.TaskConfigWithLimit, error) { - list, err := GetTaskConfigPageWithDeleted(opt) +func GetTaskConfigWithLimitList(opt models.ListOptions) (*models.TaskConfigWithLimitResponse, error) { + list, n, err := GetTaskConfigPageWithDeleted(opt) if err != nil { return nil, err } if len(list) == 0 { return nil, nil } - r := make([]*models.TaskConfigWithLimit, 0) - l, err := limiter.GetLimitersByLimitTypeWithDeleted(models.LimitTypeTask) - if err != nil { - log.Error(" GetLimitersByLimitType from redis error. %v", err) - return nil, err - } + r := make([]*models.TaskConfigWithSingleLimit, 0) for i := 0; i < len(list); i++ { li := list[i] - t := &models.TaskConfigWithLimit{ - TaskCode: li.TaskCode, - Tittle: li.Tittle, - AwardType: li.AwardType, - AwardAmount: li.AwardAmount, - Creator: li.CreatorName, - CreatedUnix: li.CreatedUnix, - IsDeleted: li.DeletedAt > 0, - DeleteAt: li.DeletedAt, + t := &models.TaskConfigWithSingleLimit{ + ID: li.TaskConfig.ID, + TaskCode: li.TaskConfig.TaskCode, + AwardType: li.TaskConfig.AwardType, + AwardAmount: li.TaskConfig.AwardAmount, + Creator: li.TaskConfig.CreatorName, + CreatedUnix: li.TaskConfig.CreatedUnix, + IsDeleted: li.TaskConfig.DeletedAt > 0, + DeleteAt: li.TaskConfig.DeletedAt, + LimitNum: li.LimitConfig.LimitNum, + RefreshRate: li.LimitConfig.RefreshRate, } - lv := make([]*models.LimitConfigVO, 0) - for j := 0; j < len(l); j++ { - lj := l[j] - if lj.LimitCode == li.TaskCode { - lv = append(lv, lj.ToLimitConfigVO()) - } - } - t.Limiters = lv r = append(r, t) } - return r, nil + + return &models.TaskConfigWithLimitResponse{ + Records: r, + Page: opt.Page, + PageSize: opt.PageSize, + Total: n, + }, nil } func AddTaskConfig(config models.TaskConfigWithLimit, doer *models.User) error { + if config.TaskCode == "" || config.AwardType == "" { + log.Error(" EditTaskConfig param error") + return errors.New("param error") + } + var lock = redis_lock.NewDistributeLock(redis_key.TaskConfigOperateLock(config.TaskCode, config.AwardType)) + isOk, _ := lock.LockWithWait(3*time.Second, 3*time.Second) + if !isOk { + return errors.New("Get lock failed") + } + defer lock.UnLock() + t, err := models.GetTaskConfigByTaskCode(config.TaskCode) if err != nil && !models.IsErrRecordNotExist(err) { return err @@ -112,20 +118,46 @@ func AddTaskConfig(config models.TaskConfigWithLimit, doer *models.User) error { return errors.New("task config is exist") } - return EditTaskConfig(config, doer) + for i, l := range config.Limiters { + if l.Scope == "" { + config.Limiters[i].Scope = models.LimitScopeSingleUser.Name() + } + } + err = models.NewTaskConfig(config, doer) + if err != nil { + log.Error("add task config error,config:%v err:%v", config, err) + return err + } + redis_client.Del(redis_key.LimitConfig(models.LimitTypeTask.Name())) + redis_client.Del(redis_key.TaskConfigList()) + return nil } func EditTaskConfig(config models.TaskConfigWithLimit, doer *models.User) error { - if config.TaskCode == "" || config.AwardType == "" { - log.Error(" AddTaskConfig param error") + if config.TaskCode == "" || config.AwardType == "" || config.ID <= 0 { + log.Error(" EditTaskConfig param error") return errors.New("param error") } + var lock = redis_lock.NewDistributeLock(redis_key.TaskConfigOperateLock(config.TaskCode, config.AwardType)) + isOk, _ := lock.LockWithWait(3*time.Second, 3*time.Second) + if !isOk { + return errors.New("Get lock failed") + } + defer lock.UnLock() + t, err := models.GetTaskConfigByID(config.ID) + if err != nil { + return err + } + if t == nil { + return errors.New("task config is not exist") + } + for i, l := range config.Limiters { if l.Scope == "" { config.Limiters[i].Scope = models.LimitScopeSingleUser.Name() } } - err := models.AddTaskConfig(config, doer) + err = models.EditTaskConfig(config, doer) if err != nil { log.Error("add task config error,config:%v err:%v", config, err) return err @@ -135,12 +167,12 @@ func EditTaskConfig(config models.TaskConfigWithLimit, doer *models.User) error return nil } -func DelTaskConfig(taskCode string) error { - if taskCode == "" { - log.Error(" AddTaskConfig param error") +func DelTaskConfig(id int64, doer *models.User) error { + if id == 0 { + log.Error(" EditTaskConfig param error") return errors.New("param error") } - err := models.DelTaskConfig(taskCode) + err := models.DelTaskConfig(id, doer) if err != nil { log.Error("del task config error,err:%v", err) return err