@@ -57,6 +57,7 @@ type LimitConfig struct { | |||||
LimitNum int64 `xorm:"NOT NULL"` | LimitNum int64 `xorm:"NOT NULL"` | ||||
LimitCode string | LimitCode string | ||||
LimitType string `xorm:"NOT NULL"` | LimitType string `xorm:"NOT NULL"` | ||||
RelatedId int64 `xorm:"INDEX"` | |||||
CreatorId int64 `xorm:"NOT NULL"` | CreatorId int64 `xorm:"NOT NULL"` | ||||
CreatorName string | CreatorName string | ||||
DeleterId int64 | DeleterId int64 | ||||
@@ -102,9 +103,9 @@ func GetLimitConfigByLimitType(limitType LimitType) ([]LimitConfig, error) { | |||||
return r, nil | return r, nil | ||||
} | } | ||||
func GetLimitersByLimitTypeWithDeleted(limitType LimitType) ([]LimitConfig, error) { | |||||
func GetLimitersByRelatedIdWithDeleted(limitType LimitType) ([]LimitConfig, error) { | |||||
r := make([]LimitConfig, 0) | 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 { | if err != nil { | ||||
return nil, err | return nil, err | ||||
} else if len(r) == 0 { | } else if len(r) == 0 { | ||||
@@ -21,10 +21,13 @@ type TaskConfig struct { | |||||
CreatorName string | CreatorName string | ||||
CreatedUnix timeutil.TimeStamp `xorm:"created"` | CreatedUnix timeutil.TimeStamp `xorm:"created"` | ||||
DeletedAt timeutil.TimeStamp `xorm:"deleted"` | DeletedAt timeutil.TimeStamp `xorm:"deleted"` | ||||
DeleterId int64 | |||||
DeleterName string | |||||
} | } | ||||
type TaskConfigWithLimit struct { | type TaskConfigWithLimit struct { | ||||
TaskCode string `binding:"Required;MaxSize(256)"` | |||||
ID int64 | |||||
TaskCode string | |||||
Tittle string | Tittle string | ||||
AwardType string | AwardType string | ||||
AwardAmount int64 | AwardAmount int64 | ||||
@@ -34,6 +37,36 @@ type TaskConfigWithLimit struct { | |||||
DeleteAt timeutil.TimeStamp | DeleteAt timeutil.TimeStamp | ||||
Limiters []*LimitConfigVO | 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 { | type BatchLimitConfigVO struct { | ||||
ConfigList []TaskConfigWithLimit | ConfigList []TaskConfigWithLimit | ||||
} | } | ||||
@@ -54,6 +87,14 @@ func GetTaskConfigByTaskCode(taskCode string) (*TaskConfig, error) { | |||||
} | } | ||||
return getTaskConfig(t) | return getTaskConfig(t) | ||||
} | } | ||||
func GetTaskConfigByID(id int64) (*TaskConfig, error) { | |||||
t := &TaskConfig{ | |||||
ID: id, | |||||
} | |||||
return getTaskConfig(t) | |||||
} | |||||
func GetTaskConfigList() ([]*TaskConfig, error) { | func GetTaskConfigList() ([]*TaskConfig, error) { | ||||
r := make([]*TaskConfig, 0) | r := make([]*TaskConfig, 0) | ||||
err := x.Find(&r) | err := x.Find(&r) | ||||
@@ -65,34 +106,40 @@ func GetTaskConfigList() ([]*TaskConfig, error) { | |||||
} | } | ||||
return r, nil | return r, nil | ||||
} | } | ||||
func GetTaskConfigPageWithDeleted(opt ListOptions) ([]*TaskConfig, error) { | |||||
func GetTaskConfigPageWithDeleted(opt ListOptions) ([]*TaskAndLimiterConfig, int64, error) { | |||||
if opt.Page <= 0 { | if opt.Page <= 0 { | ||||
opt.Page = 1 | 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 { | 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 { | 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() | sess := x.NewSession() | ||||
defer sess.Close() | defer sess.Close() | ||||
//delete old task config | //delete old task config | ||||
p := &TaskConfig{ | p := &TaskConfig{ | ||||
TaskCode: config.TaskCode, | |||||
ID: config.ID, | |||||
} | } | ||||
_, err := sess.Delete(p) | _, err := sess.Delete(p) | ||||
if err != nil { | if err != nil { | ||||
sess.Rollback() | sess.Rollback() | ||||
return err | return err | ||||
} | } | ||||
//update deleter | |||||
p.DeleterId = doer.ID | |||||
p.DeleterName = doer.Name | |||||
sess.Where("id = ?", config.ID).Unscoped().Update(p) | |||||
//add new config | //add new config | ||||
t := &TaskConfig{ | t := &TaskConfig{ | ||||
@@ -103,7 +150,7 @@ func AddTaskConfig(config TaskConfigWithLimit, doer *User) error { | |||||
CreatorId: doer.ID, | CreatorId: doer.ID, | ||||
CreatorName: doer.Name, | CreatorName: doer.Name, | ||||
} | } | ||||
_, err = sess.Insert(t) | |||||
_, err = sess.InsertOne(t) | |||||
if err != nil { | if err != nil { | ||||
sess.Rollback() | sess.Rollback() | ||||
return err | return err | ||||
@@ -111,20 +158,69 @@ func AddTaskConfig(config TaskConfigWithLimit, doer *User) error { | |||||
//delete old limiter config | //delete old limiter config | ||||
lp := &LimitConfig{ | lp := &LimitConfig{ | ||||
LimitType: LimitTypeTask.Name(), | |||||
LimitCode: config.TaskCode, | |||||
RelatedId: config.ID, | |||||
} | } | ||||
_, err = sess.Delete(lp) | _, err = sess.Delete(lp) | ||||
if err != nil { | if err != nil { | ||||
sess.Rollback() | sess.Rollback() | ||||
return err | 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 | //add new limiter config | ||||
if config.Limiters != nil && len(config.Limiters) > 0 { | if config.Limiters != nil && len(config.Limiters) > 0 { | ||||
for _, v := range config.Limiters { | for _, v := range config.Limiters { | ||||
//add new config | //add new config | ||||
l := &LimitConfig{ | l := &LimitConfig{ | ||||
RelatedId: t.ID, | |||||
Tittle: v.Tittle, | Tittle: v.Tittle, | ||||
RefreshRate: v.RefreshRate, | RefreshRate: v.RefreshRate, | ||||
Scope: v.Scope, | Scope: v.Scope, | ||||
@@ -145,30 +241,36 @@ func AddTaskConfig(config TaskConfigWithLimit, doer *User) error { | |||||
return nil | return nil | ||||
} | } | ||||
func DelTaskConfig(taskCode string) error { | |||||
func DelTaskConfig(id int64, doer *User) error { | |||||
sess := x.NewSession() | sess := x.NewSession() | ||||
defer sess.Close() | defer sess.Close() | ||||
//delete old task config | //delete old task config | ||||
p := &TaskConfig{ | p := &TaskConfig{ | ||||
TaskCode: taskCode, | |||||
ID: id, | |||||
} | } | ||||
_, err := sess.Delete(p) | _, err := sess.Delete(p) | ||||
if err != nil { | if err != nil { | ||||
sess.Rollback() | sess.Rollback() | ||||
return err | return err | ||||
} | } | ||||
//update deleter | |||||
p.DeleterId = doer.ID | |||||
p.DeleterName = doer.Name | |||||
sess.Where("id = ?", id).Unscoped().Update(p) | |||||
//delete old limiter config | //delete old limiter config | ||||
lp := &LimitConfig{ | lp := &LimitConfig{ | ||||
LimitType: LimitTypeTask.Name(), | |||||
LimitCode: taskCode, | |||||
RelatedId: id, | |||||
} | } | ||||
_, err = sess.Delete(lp) | _, err = sess.Delete(lp) | ||||
if err != nil { | if err != nil { | ||||
sess.Rollback() | sess.Rollback() | ||||
return err | return err | ||||
} | } | ||||
lp.DeleterName = doer.Name | |||||
lp.DeleterId = doer.ID | |||||
//update deleter | |||||
sess.Where("related_id = ?", id).Unscoped().Update(lp) | |||||
sess.Commit() | sess.Commit() | ||||
return nil | return nil | ||||
} | } |
@@ -9,3 +9,6 @@ func TaskAccomplishLock(sourceId string, taskType string) string { | |||||
func TaskConfigList() string { | func TaskConfigList() string { | ||||
return KeyJoin(TASK_REDIS_PREFIX, "config", "list") | return KeyJoin(TASK_REDIS_PREFIX, "config", "list") | ||||
} | } | ||||
func TaskConfigOperateLock(taskCode, rewardType string) string { | |||||
return KeyJoin(TASK_REDIS_PREFIX, "config", "operate", "lock") | |||||
} |
@@ -35,8 +35,8 @@ func GetPointAccount(ctx *context.Context) { | |||||
} | } | ||||
func GetPointRecordList(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 | var orderBy models.RewardOperateOrderBy | ||||
switch ctx.Query("sort") { | switch ctx.Query("sort") { | ||||
default: | default: | ||||
@@ -11,7 +11,7 @@ import ( | |||||
) | ) | ||||
func GetTaskConfigList(ctx *context.Context) { | func GetTaskConfigList(ctx *context.Context) { | ||||
page := ctx.QueryInt("page") | |||||
page := ctx.QueryInt("Page") | |||||
r, err := task.GetTaskConfigWithLimitList(models.ListOptions{PageSize: 20, Page: page}) | r, err := task.GetTaskConfigWithLimitList(models.ListOptions{PageSize: 20, Page: page}) | ||||
if err != nil { | if err != nil { | ||||
ctx.JSON(http.StatusOK, response.ServerError(err.Error())) | ctx.JSON(http.StatusOK, response.ServerError(err.Error())) | ||||
@@ -30,7 +30,7 @@ func OperateTaskConfig(ctx *context.Context, config models.TaskConfigWithLimit) | |||||
case "new": | case "new": | ||||
err = task.AddTaskConfig(config, ctx.User) | err = task.AddTaskConfig(config, ctx.User) | ||||
case "del": | case "del": | ||||
err = task.DelTaskConfig(config.TaskCode) | |||||
err = task.DelTaskConfig(config.ID, ctx.User) | |||||
default: | default: | ||||
err = errors.New("action type error") | err = errors.New("action type error") | ||||
} | } | ||||
@@ -246,8 +246,8 @@ func GetLimitersByLimitType(limitType models.LimitType) ([]models.LimitConfig, e | |||||
return limiters, nil | 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 err != nil { | ||||
if models.IsErrRecordNotExist(err) { | if models.IsErrRecordNotExist(err) { | ||||
return nil, nil | return nil, nil | ||||
@@ -5,7 +5,7 @@ import ( | |||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/redis/redis_client" | "code.gitea.io/gitea/modules/redis/redis_client" | ||||
"code.gitea.io/gitea/modules/redis/redis_key" | "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" | "encoding/json" | ||||
"errors" | "errors" | ||||
"time" | "time" | ||||
@@ -52,58 +52,64 @@ func GetTaskConfigList() ([]*models.TaskConfig, error) { | |||||
return config, nil | 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 { | if err != nil { | ||||
log.Error(" GetTaskConfigPageWithDeleted from model error. %v", err) | log.Error(" GetTaskConfigPageWithDeleted from model error. %v", err) | ||||
if models.IsErrRecordNotExist(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 { | if err != nil { | ||||
return nil, err | return nil, err | ||||
} | } | ||||
if len(list) == 0 { | if len(list) == 0 { | ||||
return nil, nil | 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++ { | for i := 0; i < len(list); i++ { | ||||
li := 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) | 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 { | 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) | t, err := models.GetTaskConfigByTaskCode(config.TaskCode) | ||||
if err != nil && !models.IsErrRecordNotExist(err) { | if err != nil && !models.IsErrRecordNotExist(err) { | ||||
return err | return err | ||||
@@ -112,20 +118,46 @@ func AddTaskConfig(config models.TaskConfigWithLimit, doer *models.User) error { | |||||
return errors.New("task config is exist") | 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 { | 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") | 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 { | for i, l := range config.Limiters { | ||||
if l.Scope == "" { | if l.Scope == "" { | ||||
config.Limiters[i].Scope = models.LimitScopeSingleUser.Name() | config.Limiters[i].Scope = models.LimitScopeSingleUser.Name() | ||||
} | } | ||||
} | } | ||||
err := models.AddTaskConfig(config, doer) | |||||
err = models.EditTaskConfig(config, doer) | |||||
if err != nil { | if err != nil { | ||||
log.Error("add task config error,config:%v err:%v", config, err) | log.Error("add task config error,config:%v err:%v", config, err) | ||||
return err | return err | ||||
@@ -135,12 +167,12 @@ func EditTaskConfig(config models.TaskConfigWithLimit, doer *models.User) error | |||||
return nil | 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") | return errors.New("param error") | ||||
} | } | ||||
err := models.DelTaskConfig(taskCode) | |||||
err := models.DelTaskConfig(id, doer) | |||||
if err != nil { | if err != nil { | ||||
log.Error("del task config error,err:%v", err) | log.Error("del task config error,err:%v", err) | ||||
return err | return err | ||||