| @@ -412,3 +412,18 @@ func GetUnTransformedActions() ([]*Action, error) { | |||||
| Find(&actions) | Find(&actions) | ||||
| return actions, err | return actions, err | ||||
| } | } | ||||
| func GetActionByIds(ids []int64) ([]*Action, error) { | |||||
| if len(ids) == 0 { | |||||
| return nil, nil | |||||
| } | |||||
| actions := make([]*Action, 0) | |||||
| err := x.In("id", ids).Find(&actions) | |||||
| if err != nil { | |||||
| return nil, err | |||||
| } | |||||
| if err := ActionList(actions).LoadAttributes(); err != nil { | |||||
| return nil, fmt.Errorf("ActionList loadAttributes: %v", err) | |||||
| } | |||||
| return actions, nil | |||||
| } | |||||
| @@ -168,6 +168,72 @@ type Cloudbrain struct { | |||||
| EndTime timeutil.TimeStamp | EndTime timeutil.TimeStamp | ||||
| } | } | ||||
| type CloudbrainShow struct { | |||||
| JobID string `xorm:"INDEX NOT NULL"` | |||||
| JobType string `xorm:"INDEX NOT NULL DEFAULT 'DEBUG'"` | |||||
| JobName string | |||||
| DisplayJobName string | |||||
| Status string | |||||
| UserID int64 `xorm:"INDEX NOT NULL"` | |||||
| RepoID int64 `xorm:"INDEX NOT NULL"` | |||||
| SubTaskName string | |||||
| ContainerID string | |||||
| ContainerIp string | |||||
| CreatedUnix timeutil.TimeStamp `xorm:"INDEX"` | |||||
| UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||||
| Duration int64 `xorm:"DEFAULT 0"` //运行时长 单位秒 | |||||
| TrainJobDuration string `xorm:"DEFAULT '00:00:00'"` | |||||
| Image string //镜像名称 | |||||
| GpuQueue string //GPU类型即GPU队列 | |||||
| ResourceSpecId int //GPU规格id | |||||
| DeletedAt time.Time `xorm:"deleted"` | |||||
| CanDebug bool `xorm:"-"` | |||||
| CanDel bool `xorm:"-"` | |||||
| CanModify bool `xorm:"-"` | |||||
| Type int | |||||
| BenchmarkTypeID int | |||||
| BenchmarkChildTypeID int | |||||
| VersionID int64 //版本id | |||||
| VersionName string `xorm:"INDEX"` //当前版本 | |||||
| Uuid string //数据集id | |||||
| DatasetName string | |||||
| VersionCount int //任务的当前版本数量,不包括删除的 | |||||
| IsLatestVersion string //是否是最新版本,1是,0否 | |||||
| CommitID string //提交的仓库代码id | |||||
| PreVersionName string //父版本名称 | |||||
| ComputeResource string //计算资源,例如npu | |||||
| EngineID int64 //引擎id | |||||
| TrainUrl string //输出模型的obs路径 | |||||
| BranchName string //分支名称 | |||||
| Parameters string //传给modelarts的param参数 | |||||
| BootFile string //启动文件 | |||||
| DataUrl string //数据集的obs路径 | |||||
| LogUrl string //日志输出的obs路径 | |||||
| PreVersionId int64 //父版本的版本id | |||||
| FlavorCode string //modelarts上的规格id | |||||
| Description string `xorm:"varchar(256)"` //描述 | |||||
| WorkServerNumber int //节点数 | |||||
| FlavorName string //规格名称 | |||||
| EngineName string //引擎名称 | |||||
| TotalVersionCount int //任务的所有版本数量,包括删除的 | |||||
| LabelName string //标签名称 | |||||
| ModelName string //模型名称 | |||||
| ModelVersion string //模型版本 | |||||
| CkptName string //权重文件名称 | |||||
| ResultUrl string //推理结果的obs路径 | |||||
| User *User `xorm:"-"` | |||||
| Repo *Repository `xorm:"-"` | |||||
| BenchmarkType string `xorm:"-"` //算法评测,模型评测 | |||||
| BenchmarkTypeName string `xorm:"-"` | |||||
| BenchmarkTypeRankLink string `xorm:"-"` | |||||
| StartTime timeutil.TimeStamp | |||||
| EndTime timeutil.TimeStamp | |||||
| } | |||||
| func (task *Cloudbrain) ComputeAndSetDuration() { | func (task *Cloudbrain) ComputeAndSetDuration() { | ||||
| var d int64 | var d int64 | ||||
| if task.StartTime == 0 { | if task.StartTime == 0 { | ||||
| @@ -1844,9 +1910,51 @@ func CloudbrainAllStatic(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, er | |||||
| func GetStartedCloudbrainTaskByUpdatedUnix(startTime, endTime time.Time) ([]Cloudbrain, error) { | func GetStartedCloudbrainTaskByUpdatedUnix(startTime, endTime time.Time) ([]Cloudbrain, error) { | ||||
| r := make([]Cloudbrain, 0) | r := make([]Cloudbrain, 0) | ||||
| err := x.Where("updated_unix >= ? and updated_unix <= ? and start_time > 0", startTime.Unix(), endTime.Unix()).Find(&r) | |||||
| err := x.Where("updated_unix >= ? and updated_unix <= ? and start_time > 0", startTime.Unix(), endTime.Unix()).Unscoped().Find(&r) | |||||
| if err != nil { | if err != nil { | ||||
| return nil, err | return nil, err | ||||
| } | } | ||||
| return r, nil | return r, nil | ||||
| } | } | ||||
| func GetCloudbrainByIds(ids []int64) ([]Cloudbrain, error) { | |||||
| if len(ids) == 0 { | |||||
| return nil, nil | |||||
| } | |||||
| cloudbrains := make([]Cloudbrain, 0) | |||||
| err := x.In("id", ids).Unscoped().Find(&cloudbrains) | |||||
| if err != nil { | |||||
| return nil, err | |||||
| } | |||||
| return cloudbrains, nil | |||||
| } | |||||
| var ( | |||||
| DebugResourceSpecs *ResourceSpecs | |||||
| TrainResourceSpecs *ResourceSpecs | |||||
| ) | |||||
| func GetResourceSpec(jobType string, resourceSpecId int) *ResourceSpec { | |||||
| if jobType == string(JobTypeTrain) { | |||||
| if TrainResourceSpecs == nil { | |||||
| json.Unmarshal([]byte(setting.TrainResourceSpecs), &TrainResourceSpecs) | |||||
| } | |||||
| for _, spec := range TrainResourceSpecs.ResourceSpec { | |||||
| if resourceSpecId == spec.Id { | |||||
| return spec | |||||
| } | |||||
| } | |||||
| } else { | |||||
| if DebugResourceSpecs == nil { | |||||
| json.Unmarshal([]byte(setting.ResourceSpecs), &DebugResourceSpecs) | |||||
| } | |||||
| for _, spec := range DebugResourceSpecs.ResourceSpec { | |||||
| if resourceSpecId == spec.Id { | |||||
| return spec | |||||
| } | |||||
| } | |||||
| } | |||||
| return nil | |||||
| } | |||||
| @@ -2,6 +2,7 @@ package models | |||||
| import ( | import ( | ||||
| "code.gitea.io/gitea/modules/timeutil" | "code.gitea.io/gitea/modules/timeutil" | ||||
| "strings" | |||||
| ) | ) | ||||
| const ( | const ( | ||||
| @@ -44,3 +45,17 @@ func UpdateRewardAdminLogStatus(logId string, oldStatus, newStatus int) error { | |||||
| } | } | ||||
| return nil | return nil | ||||
| } | } | ||||
| func GetRewardAdminLogByLogIds(logIds []string) ([]RewardAdminLog, error) { | |||||
| if len(logIds) == 0 { | |||||
| return nil, nil | |||||
| } | |||||
| adminLogs := make([]RewardAdminLog, 0) | |||||
| err := x.SQL("select rdl.id,rdl.log_id,rdl.amount,rdl.reward_type,rdl.remark,rdl.status,rdl.target_user_id,rdl.creator_id,u.name as creator_name "+ | |||||
| "from reward_admin_log rdl left join public.user u on rdl.creator_id = u.id "+ | |||||
| "where rdl.log_id in (?)", strings.Join(logIds, ",")).Find(&adminLogs) | |||||
| if err != nil { | |||||
| return nil, err | |||||
| } | |||||
| return adminLogs, nil | |||||
| } | |||||
| @@ -2,6 +2,8 @@ package models | |||||
| import ( | import ( | ||||
| "code.gitea.io/gitea/modules/timeutil" | "code.gitea.io/gitea/modules/timeutil" | ||||
| "fmt" | |||||
| "strconv" | |||||
| "strings" | "strings" | ||||
| "xorm.io/builder" | "xorm.io/builder" | ||||
| ) | ) | ||||
| @@ -112,21 +114,120 @@ const ( | |||||
| RewardOrderByIDDesc RewardOperateOrderBy = "id desc" | RewardOrderByIDDesc RewardOperateOrderBy = "id desc" | ||||
| ) | ) | ||||
| type RewardRecordList []*RewardOperateRecord | |||||
| type RewardRecordShowList []*RewardOperateRecordShow | |||||
| func (l *RewardRecordList) ToShow() (RewardRecordShowList, error) { | |||||
| actionMap, err := l.GetRewardRecordAction() | |||||
| adminLogMap, err := l.GetRewardRecordAdminLog() | |||||
| CloudbrainMap, err := l.GetRewardRecordCloudbrainTask() | |||||
| if err != nil { | |||||
| return nil, err | |||||
| } | |||||
| result := make([]*RewardOperateRecordShow, 0) | |||||
| for _, v := range *l { | |||||
| temp := v.ToShow() | |||||
| switch v.SourceType { | |||||
| case SourceTypeAccomplishTask.Name(): | |||||
| temp.Action = actionMap[v.SourceId] | |||||
| case SourceTypeAdminOperate.Name(): | |||||
| temp.AdminLog = adminLogMap[v.SourceId] | |||||
| case SourceTypeRunCloudbrainTask.Name(): | |||||
| temp.Cloudbrain = CloudbrainMap[v.SourceId] | |||||
| } | |||||
| result = append(result, &temp) | |||||
| } | |||||
| return result, nil | |||||
| } | |||||
| func (l *RewardRecordList) GetRewardRecordAction() (map[string]Action, error) { | |||||
| if len(*l) == 0 { | |||||
| return nil, nil | |||||
| } | |||||
| actionIds := make([]int64, 0) | |||||
| for _, r := range *l { | |||||
| if r.SourceType != SourceTypeAccomplishTask.Name() { | |||||
| continue | |||||
| } | |||||
| i, _ := strconv.ParseInt(r.SourceId, 10, 64) | |||||
| actionIds = append(actionIds, i) | |||||
| } | |||||
| actions, err := GetActionByIds(actionIds) | |||||
| if err != nil { | |||||
| return nil, err | |||||
| } | |||||
| result := make(map[string]Action, 0) | |||||
| for _, v := range actions { | |||||
| result[fmt.Sprint(v.ID)] = *v | |||||
| } | |||||
| return result, nil | |||||
| } | |||||
| func (l *RewardRecordList) GetRewardRecordAdminLog() (map[string]RewardAdminLog, error) { | |||||
| if len(*l) == 0 { | |||||
| return nil, nil | |||||
| } | |||||
| logIds := make([]string, 0) | |||||
| for _, r := range *l { | |||||
| if r.SourceType != SourceTypeAdminOperate.Name() { | |||||
| continue | |||||
| } | |||||
| logIds = append(logIds, r.SourceId) | |||||
| } | |||||
| logs, err := GetRewardAdminLogByLogIds(logIds) | |||||
| if err != nil { | |||||
| return nil, err | |||||
| } | |||||
| result := make(map[string]RewardAdminLog, 0) | |||||
| for _, v := range logs { | |||||
| result[fmt.Sprint(v.LogId)] = v | |||||
| } | |||||
| return result, nil | |||||
| } | |||||
| func (l *RewardRecordList) GetRewardRecordCloudbrainTask() (map[string]Cloudbrain, error) { | |||||
| if len(*l) == 0 { | |||||
| return nil, nil | |||||
| } | |||||
| cloudbrainIds := make([]int64, 0) | |||||
| for _, r := range *l { | |||||
| if r.SourceType != SourceTypeRunCloudbrainTask.Name() { | |||||
| continue | |||||
| } | |||||
| i, _ := strconv.ParseInt(r.SourceId, 10, 64) | |||||
| cloudbrainIds = append(cloudbrainIds, i) | |||||
| } | |||||
| cloudbrains, err := GetCloudbrainByIds(cloudbrainIds) | |||||
| if err != nil { | |||||
| return nil, err | |||||
| } | |||||
| result := make(map[string]Cloudbrain, 0) | |||||
| for _, v := range cloudbrains { | |||||
| result[fmt.Sprint(v.ID)] = v | |||||
| } | |||||
| return result, nil | |||||
| } | |||||
| type RewardOperateRecord struct { | type RewardOperateRecord struct { | ||||
| ID int64 `xorm:"pk autoincr"` | |||||
| SerialNo string `xorm:"INDEX NOT NULL"` | |||||
| UserId int64 `xorm:"INDEX NOT NULL"` | |||||
| Amount int64 `xorm:"NOT NULL"` | |||||
| Tittle string | |||||
| RewardType string `xorm:"NOT NULL"` | |||||
| SourceType string `xorm:"NOT NULL"` | |||||
| SourceId string `xorm:"INDEX NOT NULL"` | |||||
| RequestId string `xorm:"INDEX NOT NULL"` | |||||
| OperateType string `xorm:"NOT NULL"` | |||||
| Status string `xorm:"NOT NULL"` | |||||
| Remark string | |||||
| CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
| UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||||
| ID int64 `xorm:"pk autoincr"` | |||||
| SerialNo string `xorm:"INDEX NOT NULL"` | |||||
| UserId int64 `xorm:"INDEX NOT NULL"` | |||||
| Amount int64 `xorm:"NOT NULL"` | |||||
| Tittle string | |||||
| RewardType string `xorm:"NOT NULL"` | |||||
| SourceType string `xorm:"NOT NULL"` | |||||
| SourceId string `xorm:"INDEX NOT NULL"` | |||||
| RequestId string `xorm:"INDEX NOT NULL"` | |||||
| OperateType string `xorm:"NOT NULL"` | |||||
| Status string `xorm:"NOT NULL"` | |||||
| Remark string | |||||
| CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
| UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||||
| FinishedUnix timeutil.TimeStamp `xorm:"INDEX"` | |||||
| } | } | ||||
| type AdminRewardOperateReq struct { | type AdminRewardOperateReq struct { | ||||
| @@ -144,6 +245,8 @@ func (r RewardOperateRecord) ToShow() RewardOperateRecordShow { | |||||
| OperateType: r.OperateType, | OperateType: r.OperateType, | ||||
| Amount: r.Amount, | Amount: r.Amount, | ||||
| Remark: r.Remark, | Remark: r.Remark, | ||||
| Status: r.Status, | |||||
| SourceType: r.SourceType, | |||||
| } | } | ||||
| } | } | ||||
| @@ -153,10 +256,11 @@ type RewardOperateRecordShow struct { | |||||
| Status string | Status string | ||||
| OperateType string | OperateType string | ||||
| Amount int64 | Amount int64 | ||||
| Remark string | |||||
| SourceType string | |||||
| Action Action | Action Action | ||||
| Cloudbrain Cloudbrain | Cloudbrain Cloudbrain | ||||
| SourceType SourceType | |||||
| Remark string | |||||
| AdminLog RewardAdminLog | |||||
| } | } | ||||
| func getPointOperateRecord(tl *RewardOperateRecord) (*RewardOperateRecord, error) { | func getPointOperateRecord(tl *RewardOperateRecord) (*RewardOperateRecord, error) { | ||||
| @@ -189,11 +293,12 @@ func InsertRewardOperateRecord(tl *RewardOperateRecord) (int64, error) { | |||||
| return x.Insert(tl) | return x.Insert(tl) | ||||
| } | } | ||||
| func UpdateAwardOperateRecordStatus(sourceType, requestId, oldStatus, newStatus string) (int64, error) { | |||||
| func UpdateRewardRecordToFinalStatus(sourceType, requestId, newStatus string) (int64, error) { | |||||
| r := &RewardOperateRecord{ | r := &RewardOperateRecord{ | ||||
| Status: newStatus, | |||||
| Status: newStatus, | |||||
| FinishedUnix: timeutil.TimeStampNow(), | |||||
| } | } | ||||
| return x.Cols("status").Where("source_type=? and request_id=? and status=?", sourceType, requestId, oldStatus).Update(r) | |||||
| return x.Cols("status", "finished_unix").Where("source_type=? and request_id=? and status=?", sourceType, requestId, OperateStatusOperating).Update(r) | |||||
| } | } | ||||
| func SumRewardAmountInTaskPeriod(rewardType string, sourceType string, userId int64, period *PeriodResult) (int64, error) { | func SumRewardAmountInTaskPeriod(rewardType string, sourceType string, userId int64, period *PeriodResult) (int64, error) { | ||||
| @@ -252,7 +357,7 @@ type RewardRecordListOpts struct { | |||||
| OrderBy RewardOperateOrderBy | OrderBy RewardOperateOrderBy | ||||
| } | } | ||||
| func GetRewardRecordList(opts RewardRecordListOpts) ([]RewardOperateRecord, int64, error) { | |||||
| func GetRewardRecordList(opts RewardRecordListOpts) (RewardRecordList, int64, error) { | |||||
| if opts.Page <= 0 { | if opts.Page <= 0 { | ||||
| opts.Page = 1 | opts.Page = 1 | ||||
| } | } | ||||
| @@ -261,7 +366,7 @@ func GetRewardRecordList(opts RewardRecordListOpts) ([]RewardOperateRecord, int6 | |||||
| opts.OrderBy = RewardOrderByIDDesc | opts.OrderBy = RewardOrderByIDDesc | ||||
| } | } | ||||
| r := make([]RewardOperateRecord, 0) | |||||
| r := make([]*RewardOperateRecord, 0) | |||||
| cond := builder.NewCond() | cond := builder.NewCond() | ||||
| if opts.UserId > 0 { | if opts.UserId > 0 { | ||||
| cond = cond.And(builder.Eq{"user_id": opts.UserId}) | cond = cond.And(builder.Eq{"user_id": opts.UserId}) | ||||
| @@ -77,7 +77,7 @@ func IncrRewardTaskSuccessCount(t RewardPeriodicTask, count int64, nextTime time | |||||
| sess.Rollback() | sess.Rollback() | ||||
| return err | return err | ||||
| } | } | ||||
| _, err = sess.Exec("update reward_operate_record set amount = amount + ? ,updated_unix = ? where serial_no = ?", count*t.Amount, timeutil.TimeStampNow(), t.OperateSerialNo) | |||||
| _, err = sess.Exec("update reward_operate_record set amount = amount + ? ,updated_unix = ? where serial_no = ?", t.Amount, timeutil.TimeStampNow(), t.OperateSerialNo) | |||||
| if err != nil { | if err != nil { | ||||
| sess.Rollback() | sess.Rollback() | ||||
| return err | return err | ||||
| @@ -7,7 +7,6 @@ import ( | |||||
| type TaskAccomplishLog struct { | type TaskAccomplishLog struct { | ||||
| ID int64 `xorm:"pk autoincr"` | ID int64 `xorm:"pk autoincr"` | ||||
| LogId string `xorm:"INDEX NOT NULL"` | |||||
| ConfigId int64 `xorm:"NOT NULL"` | ConfigId int64 `xorm:"NOT NULL"` | ||||
| TaskCode string `xorm:"NOT NULL"` | TaskCode string `xorm:"NOT NULL"` | ||||
| UserId int64 `xorm:"INDEX NOT NULL"` | UserId int64 `xorm:"INDEX NOT NULL"` | ||||
| @@ -251,6 +251,6 @@ func initBasicTasks() { | |||||
| registerSyncCloudbrainStatus() | registerSyncCloudbrainStatus() | ||||
| registerHandleOrgStatistic() | registerHandleOrgStatistic() | ||||
| registerRewardPeriodTask() | |||||
| //registerRewardPeriodTask() | |||||
| registerCloudbrainPointDeductTask() | registerCloudbrainPointDeductTask() | ||||
| } | } | ||||
| @@ -2,7 +2,7 @@ package repo | |||||
| import ( | import ( | ||||
| "bufio" | "bufio" | ||||
| "code.gitea.io/gitea/services/reward" | |||||
| "code.gitea.io/gitea/services/reward/point/account" | |||||
| "encoding/json" | "encoding/json" | ||||
| "errors" | "errors" | ||||
| "fmt" | "fmt" | ||||
| @@ -230,7 +230,7 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||||
| command = commandTrain | command = commandTrain | ||||
| } | } | ||||
| if !reward.IsPointBalanceEnough(ctx.User.ID, jobType, resourceSpecId) { | |||||
| if !account.IsPointBalanceEnough(ctx.User.ID, jobType, resourceSpecId) { | |||||
| log.Error("point balance is not enough,userId=%d jobType=%s resourceSpecId=%d", ctx.User.ID, jobType, resourceSpecId) | log.Error("point balance is not enough,userId=%d jobType=%s resourceSpecId=%d", ctx.User.ID, jobType, resourceSpecId) | ||||
| cloudBrainNewDataPrepare(ctx) | cloudBrainNewDataPrepare(ctx) | ||||
| ctx.RenderWithErr(models.ErrInsufficientPointsBalance{}.Error(), tpl, &form) | ctx.RenderWithErr(models.ErrInsufficientPointsBalance{}.Error(), tpl, &form) | ||||
| @@ -318,7 +318,7 @@ func CloudBrainRestart(ctx *context.Context) { | |||||
| var status = string(models.JobWaiting) | var status = string(models.JobWaiting) | ||||
| task := ctx.Cloudbrain | task := ctx.Cloudbrain | ||||
| for { | for { | ||||
| if !reward.IsPointBalanceEnough(ctx.User.ID, task.JobType, task.ResourceSpecId) { | |||||
| if !account.IsPointBalanceEnough(ctx.User.ID, task.JobType, task.ResourceSpecId) { | |||||
| log.Error("point balance is not enough,userId=%d jobType=%s resourceSpecId=%d", ctx.User.ID, task.JobType, task.ResourceSpecId) | log.Error("point balance is not enough,userId=%d jobType=%s resourceSpecId=%d", ctx.User.ID, task.JobType, task.ResourceSpecId) | ||||
| resultCode = "-1" | resultCode = "-1" | ||||
| errorMsg = models.ErrInsufficientPointsBalance{}.Error() | errorMsg = models.ErrInsufficientPointsBalance{}.Error() | ||||
| @@ -1870,7 +1870,7 @@ func BenchMarkAlgorithmCreate(ctx *context.Context, form auth.CreateCloudBrainFo | |||||
| repo := ctx.Repo.Repository | repo := ctx.Repo.Repository | ||||
| if !reward.IsPointBalanceEnough(ctx.User.ID, string(models.JobTypeBenchmark), resourceSpecId) { | |||||
| if !account.IsPointBalanceEnough(ctx.User.ID, string(models.JobTypeBenchmark), resourceSpecId) { | |||||
| log.Error("point balance is not enough,userId=%d jobType=%s resourceSpecId=%d", ctx.User.ID, string(models.JobTypeBenchmark), resourceSpecId) | log.Error("point balance is not enough,userId=%d jobType=%s resourceSpecId=%d", ctx.User.ID, string(models.JobTypeBenchmark), resourceSpecId) | ||||
| cloudBrainNewDataPrepare(ctx) | cloudBrainNewDataPrepare(ctx) | ||||
| ctx.RenderWithErr(models.ErrInsufficientPointsBalance{}.Error(), tplCloudBrainBenchmarkNew, &form) | ctx.RenderWithErr(models.ErrInsufficientPointsBalance{}.Error(), tplCloudBrainBenchmarkNew, &form) | ||||
| @@ -2032,7 +2032,7 @@ func ModelBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainForm) | |||||
| tpl := tplCloudBrainBenchmarkNew | tpl := tplCloudBrainBenchmarkNew | ||||
| command := cloudbrain.Command | command := cloudbrain.Command | ||||
| if !reward.IsPointBalanceEnough(ctx.User.ID, jobType, resourceSpecId) { | |||||
| if !account.IsPointBalanceEnough(ctx.User.ID, jobType, resourceSpecId) { | |||||
| log.Error("point balance is not enough,userId=%d jobType=%s resourceSpecId=%d", ctx.User.ID, jobType, resourceSpecId) | log.Error("point balance is not enough,userId=%d jobType=%s resourceSpecId=%d", ctx.User.ID, jobType, resourceSpecId) | ||||
| cloudBrainNewDataPrepare(ctx) | cloudBrainNewDataPrepare(ctx) | ||||
| ctx.RenderWithErr(models.ErrInsufficientPointsBalance{}.Error(), tpl, &form) | ctx.RenderWithErr(models.ErrInsufficientPointsBalance{}.Error(), tpl, &form) | ||||
| @@ -2,7 +2,7 @@ package repo | |||||
| import ( | import ( | ||||
| "archive/zip" | "archive/zip" | ||||
| "code.gitea.io/gitea/services/reward" | |||||
| "code.gitea.io/gitea/services/reward/point/account" | |||||
| "encoding/json" | "encoding/json" | ||||
| "errors" | "errors" | ||||
| "fmt" | "fmt" | ||||
| @@ -207,7 +207,7 @@ func Notebook2Create(ctx *context.Context, form auth.CreateModelArtsNotebookForm | |||||
| repo := ctx.Repo.Repository | repo := ctx.Repo.Repository | ||||
| resourceSpecId := form.ResourceSpecId | resourceSpecId := form.ResourceSpecId | ||||
| if !reward.IsPointBalanceEnough(ctx.User.ID, string(models.JobTypeDebug), resourceSpecId) { | |||||
| if !account.IsPointBalanceEnough(ctx.User.ID, string(models.JobTypeDebug), resourceSpecId) { | |||||
| log.Error("point balance is not enough,userId=%d jobType=%s resourceSpecId=%d", ctx.User.ID, string(models.JobTypeBenchmark), resourceSpecId) | log.Error("point balance is not enough,userId=%d jobType=%s resourceSpecId=%d", ctx.User.ID, string(models.JobTypeBenchmark), resourceSpecId) | ||||
| cloudBrainNewDataPrepare(ctx) | cloudBrainNewDataPrepare(ctx) | ||||
| ctx.RenderWithErr(models.ErrInsufficientPointsBalance{}.Error(), tplModelArtsNotebookNew, &form) | ctx.RenderWithErr(models.ErrInsufficientPointsBalance{}.Error(), tplModelArtsNotebookNew, &form) | ||||
| @@ -426,7 +426,7 @@ func NotebookManage(ctx *context.Context) { | |||||
| errorMsg = "you have no right to restart the job" | errorMsg = "you have no right to restart the job" | ||||
| break | break | ||||
| } | } | ||||
| if !reward.IsPointBalanceEnough(ctx.User.ID, task.JobType, task.ResourceSpecId) { | |||||
| if !account.IsPointBalanceEnough(ctx.User.ID, task.JobType, task.ResourceSpecId) { | |||||
| log.Error("point balance is not enough,userId=%d jobType=%s resourceSpecId=%d", ctx.User.ID, task.JobType, task.ResourceSpecId) | log.Error("point balance is not enough,userId=%d jobType=%s resourceSpecId=%d", ctx.User.ID, task.JobType, task.ResourceSpecId) | ||||
| resultCode = "-1" | resultCode = "-1" | ||||
| errorMsg = models.ErrInsufficientPointsBalance{}.Error() | errorMsg = models.ErrInsufficientPointsBalance{}.Error() | ||||
| @@ -1002,7 +1002,7 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||||
| EngineName := form.EngineName | EngineName := form.EngineName | ||||
| resourceSpecId := form.ResourceSpecId | resourceSpecId := form.ResourceSpecId | ||||
| if !reward.IsPointBalanceEnough(ctx.User.ID, string(models.JobTypeTrain), resourceSpecId) { | |||||
| if !account.IsPointBalanceEnough(ctx.User.ID, string(models.JobTypeTrain), resourceSpecId) { | |||||
| log.Error("point balance is not enough,userId=%d jobType=%s resourceSpecId=%d", ctx.User.ID, string(models.JobTypeBenchmark), resourceSpecId) | log.Error("point balance is not enough,userId=%d jobType=%s resourceSpecId=%d", ctx.User.ID, string(models.JobTypeBenchmark), resourceSpecId) | ||||
| cloudBrainNewDataPrepare(ctx) | cloudBrainNewDataPrepare(ctx) | ||||
| ctx.RenderWithErr(models.ErrInsufficientPointsBalance{}.Error(), tplModelArtsTrainJobNew, &form) | ctx.RenderWithErr(models.ErrInsufficientPointsBalance{}.Error(), tplModelArtsTrainJobNew, &form) | ||||
| @@ -1851,7 +1851,7 @@ func InferenceJobCreate(ctx *context.Context, form auth.CreateModelArtsInference | |||||
| ckptUrl := form.TrainUrl + form.CkptName | ckptUrl := form.TrainUrl + form.CkptName | ||||
| if !reward.IsPointBalanceEnough(ctx.User.ID, string(models.JobTypeInference), resourceSpecId) { | |||||
| if !account.IsPointBalanceEnough(ctx.User.ID, string(models.JobTypeInference), resourceSpecId) { | |||||
| log.Error("point balance is not enough,userId=%d jobType=%s resourceSpecId=%d", ctx.User.ID, string(models.JobTypeBenchmark), resourceSpecId) | log.Error("point balance is not enough,userId=%d jobType=%s resourceSpecId=%d", ctx.User.ID, string(models.JobTypeBenchmark), resourceSpecId) | ||||
| inferenceJobErrorNewDataPrepare(ctx, form) | inferenceJobErrorNewDataPrepare(ctx, form) | ||||
| ctx.RenderWithErr(models.ErrInsufficientPointsBalance{}.Error(), tplModelArtsInferenceJobNew, &form) | ctx.RenderWithErr(models.ErrInsufficientPointsBalance{}.Error(), tplModelArtsInferenceJobNew, &form) | ||||
| @@ -13,7 +13,6 @@ import ( | |||||
| const tplPoint base.TplName = "/reward/point" | const tplPoint base.TplName = "/reward/point" | ||||
| type AccountResponse struct { | type AccountResponse struct { | ||||
| AccountCode string | |||||
| Balance int64 | Balance int64 | ||||
| TotalEarned int64 | TotalEarned int64 | ||||
| TotalConsumed int64 | TotalConsumed int64 | ||||
| @@ -4,8 +4,6 @@ import ( | |||||
| "code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
| "code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
| "code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
| "code.gitea.io/gitea/services/reward/point/account" | |||||
| "encoding/json" | |||||
| "fmt" | "fmt" | ||||
| "time" | "time" | ||||
| ) | ) | ||||
| @@ -17,34 +15,17 @@ var ( | |||||
| const RUN_CLOUDBRAIN_TASK_TITTLE = "运行云脑任务" | const RUN_CLOUDBRAIN_TASK_TITTLE = "运行云脑任务" | ||||
| //IsPointBalanceEnough check whether the user's point balance is bigger than task unit price | |||||
| func IsPointBalanceEnough(targetUserId int64, jobType string, resourceSpecId int) bool { | |||||
| func StartAndGetCloudBrainPointDeductTask(task models.Cloudbrain) (*models.RewardPeriodicTask, error) { | |||||
| if !setting.CloudBrainPaySwitch { | if !setting.CloudBrainPaySwitch { | ||||
| return true | |||||
| } | |||||
| spec := getResourceSpec(jobType, resourceSpecId) | |||||
| if spec == nil { | |||||
| return true | |||||
| } | |||||
| a, error := account.GetAccount(targetUserId) | |||||
| if error != nil { | |||||
| return false | |||||
| } | |||||
| return a.Balance >= spec.UnitPrice | |||||
| } | |||||
| func StartCloudBrainPointDeductTask(task models.Cloudbrain) { | |||||
| if !setting.CloudBrainPaySwitch { | |||||
| return | |||||
| return nil, nil | |||||
| } | } | ||||
| spec := getResourceSpec(task.JobType, task.ResourceSpecId) | |||||
| spec := models.GetResourceSpec(task.JobType, task.ResourceSpecId) | |||||
| if spec == nil || spec.UnitPrice == 0 { | if spec == nil || spec.UnitPrice == 0 { | ||||
| return | |||||
| return nil, nil | |||||
| } | } | ||||
| StartPeriodicTask(&models.StartPeriodicTaskOpts{ | |||||
| return StartAndGetPeriodicTask(&models.StartPeriodicTaskOpts{ | |||||
| SourceType: models.SourceTypeRunCloudbrainTask, | SourceType: models.SourceTypeRunCloudbrainTask, | ||||
| SourceId: getCloudBrainPointTaskSourceId(task), | SourceId: getCloudBrainPointTaskSourceId(task), | ||||
| TargetUserId: task.UserID, | TargetUserId: task.UserID, | ||||
| @@ -67,31 +48,6 @@ func getCloudBrainPointTaskSourceId(task models.Cloudbrain) string { | |||||
| return fmt.Sprint(task.ID) | return fmt.Sprint(task.ID) | ||||
| } | } | ||||
| func getResourceSpec(jobType string, resourceSpecId int) *models.ResourceSpec { | |||||
| if jobType == string(models.JobTypeTrain) { | |||||
| if TrainResourceSpecs == nil { | |||||
| json.Unmarshal([]byte(setting.TrainResourceSpecs), &TrainResourceSpecs) | |||||
| } | |||||
| for _, spec := range TrainResourceSpecs.ResourceSpec { | |||||
| if resourceSpecId == spec.Id { | |||||
| return spec | |||||
| } | |||||
| } | |||||
| } else { | |||||
| if ResourceSpecs == nil { | |||||
| json.Unmarshal([]byte(setting.ResourceSpecs), &ResourceSpecs) | |||||
| } | |||||
| for _, spec := range ResourceSpecs.ResourceSpec { | |||||
| if resourceSpecId == spec.Id { | |||||
| return spec | |||||
| } | |||||
| } | |||||
| } | |||||
| return nil | |||||
| } | |||||
| var firstTimeFlag = true | var firstTimeFlag = true | ||||
| func StartCloudbrainPointDeductTask() { | func StartCloudbrainPointDeductTask() { | ||||
| @@ -107,10 +63,9 @@ func StartCloudbrainPointDeductTask() { | |||||
| if firstTimeFlag { | if firstTimeFlag { | ||||
| //When it is executed for the first time, it needs to process the tasks of the last 1 hours. | //When it is executed for the first time, it needs to process the tasks of the last 1 hours. | ||||
| //This is done to prevent the application from hanging for a long time | //This is done to prevent the application from hanging for a long time | ||||
| start = end.Add(-1 * time.Hour) | |||||
| start = end.Add(-3 * time.Hour) | |||||
| firstTimeFlag = false | firstTimeFlag = false | ||||
| } | } | ||||
| taskList, err := models.GetStartedCloudbrainTaskByUpdatedUnix(start, end) | taskList, err := models.GetStartedCloudbrainTaskByUpdatedUnix(start, end) | ||||
| if err != nil { | if err != nil { | ||||
| log.Error("GetStartedCloudbrainTaskByUpdatedUnix error. %v", err) | log.Error("GetStartedCloudbrainTaskByUpdatedUnix error. %v", err) | ||||
| @@ -121,11 +76,30 @@ func StartCloudbrainPointDeductTask() { | |||||
| return | return | ||||
| } | } | ||||
| for _, t := range taskList { | for _, t := range taskList { | ||||
| if int64(t.StartTime) <= end.Unix() && int64(t.StartTime) >= start.Unix() { | |||||
| StartCloudBrainPointDeductTask(t) | |||||
| //初始化 period_task 和 operate_record | |||||
| if int64(t.StartTime) > end.Unix() || int64(t.StartTime) < start.Unix() { | |||||
| continue | |||||
| } | |||||
| task, err := StartAndGetCloudBrainPointDeductTask(t) | |||||
| if err != nil { | |||||
| log.Error("run cloubrain point deduct task error,err=%v", err) | |||||
| continue | |||||
| } | } | ||||
| if task == nil { | |||||
| continue | |||||
| } | |||||
| if task.Status == models.PeriodicTaskStatusFinished { | |||||
| log.Info("Periodic task is finished") | |||||
| continue | |||||
| } | |||||
| if int64(t.EndTime) <= end.Unix() && int64(t.EndTime) >= start.Unix() { | if int64(t.EndTime) <= end.Unix() && int64(t.EndTime) >= start.Unix() { | ||||
| StopCloudBrainPointDeductTask(t) | |||||
| endTime := time.Unix(int64(t.EndTime), 0) | |||||
| RunRewardTask(*task, endTime) | |||||
| models.StopPeriodicTask(task.ID, task.OperateSerialNo, endTime) | |||||
| } else { | |||||
| RunRewardTask(*task, end) | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -78,11 +78,11 @@ func Operate(ctx *models.RewardOperateContext) error { | |||||
| //operate | //operate | ||||
| if err := operator.Operate(ctx); err != nil { | if err := operator.Operate(ctx); err != nil { | ||||
| updateAwardOperateRecordStatus(ctx.SourceType.Name(), ctx.RequestId, models.OperateStatusOperating, models.OperateStatusFailed) | |||||
| UpdateRewardRecordToFinalStatus(ctx.SourceType.Name(), ctx.RequestId, models.OperateStatusFailed) | |||||
| return err | return err | ||||
| } | } | ||||
| updateAwardOperateRecordStatus(ctx.SourceType.Name(), ctx.RequestId, models.OperateStatusOperating, models.OperateStatusSucceeded) | |||||
| UpdateRewardRecordToFinalStatus(ctx.SourceType.Name(), ctx.RequestId, models.OperateStatusSucceeded) | |||||
| NotifyRewardOperation(ctx.TargetUserId, ctx.Reward.Amount, ctx.Reward.Type, ctx.OperateType) | NotifyRewardOperation(ctx.TargetUserId, ctx.Reward.Amount, ctx.Reward.Type, ctx.OperateType) | ||||
| return nil | return nil | ||||
| } | } | ||||
| @@ -160,8 +160,8 @@ func createPeriodicRewardOperateRecord(ctx *models.StartPeriodicTaskOpts) (strin | |||||
| return record.SerialNo, nil | return record.SerialNo, nil | ||||
| } | } | ||||
| func updateAwardOperateRecordStatus(sourceType, requestId, oldStatus, newStatus string) error { | |||||
| _, err := models.UpdateAwardOperateRecordStatus(sourceType, requestId, oldStatus, newStatus) | |||||
| func UpdateRewardRecordToFinalStatus(sourceType, requestId, newStatus string) error { | |||||
| _, err := models.UpdateRewardRecordToFinalStatus(sourceType, requestId, newStatus) | |||||
| if err != nil { | if err != nil { | ||||
| return err | return err | ||||
| } | } | ||||
| @@ -169,10 +169,10 @@ func updateAwardOperateRecordStatus(sourceType, requestId, oldStatus, newStatus | |||||
| } | } | ||||
| func StartPeriodicTaskAsyn(opts *models.StartPeriodicTaskOpts) { | func StartPeriodicTaskAsyn(opts *models.StartPeriodicTaskOpts) { | ||||
| go StartPeriodicTask(opts) | |||||
| go StartAndGetPeriodicTask(opts) | |||||
| } | } | ||||
| func StartPeriodicTask(opts *models.StartPeriodicTaskOpts) error { | |||||
| func StartAndGetPeriodicTask(opts *models.StartPeriodicTaskOpts) (*models.RewardPeriodicTask, error) { | |||||
| defer func() { | defer func() { | ||||
| if err := recover(); err != nil { | if err := recover(); err != nil { | ||||
| combinedErr := fmt.Errorf("%s\n%s", err, log.Stack(2)) | combinedErr := fmt.Errorf("%s\n%s", err, log.Stack(2)) | ||||
| @@ -183,35 +183,46 @@ func StartPeriodicTask(opts *models.StartPeriodicTaskOpts) error { | |||||
| var rewardLock = redis_lock.NewDistributeLock(redis_key.RewardOperateLock(opts.RequestId, opts.SourceType.Name(), opts.OperateType.Name())) | var rewardLock = redis_lock.NewDistributeLock(redis_key.RewardOperateLock(opts.RequestId, opts.SourceType.Name(), opts.OperateType.Name())) | ||||
| isOk, err := rewardLock.Lock(3 * time.Second) | isOk, err := rewardLock.Lock(3 * time.Second) | ||||
| if err != nil { | if err != nil { | ||||
| return err | |||||
| return nil, err | |||||
| } | } | ||||
| if !isOk { | if !isOk { | ||||
| log.Info("duplicated operate request,targetUserId=%d requestId=%s", opts.TargetUserId, opts.RequestId) | log.Info("duplicated operate request,targetUserId=%d requestId=%s", opts.TargetUserId, opts.RequestId) | ||||
| return nil | |||||
| return nil, nil | |||||
| } | } | ||||
| defer rewardLock.UnLock() | defer rewardLock.UnLock() | ||||
| //is handled before? | |||||
| isHandled, err := isHandled(opts.SourceType.Name(), opts.RequestId, opts.OperateType.Name()) | |||||
| if err != nil { | |||||
| log.Error("operate is handled error,%v", err) | |||||
| return err | |||||
| _, err = models.GetPointOperateRecordBySourceTypeAndRequestId(opts.SourceType.Name(), opts.RequestId, opts.OperateType.Name()) | |||||
| if err == nil { | |||||
| task, err := models.GetPeriodicTaskBySourceIdAndType(opts.SourceType, opts.SourceId, opts.OperateType) | |||||
| if err != nil { | |||||
| log.Error("GetPeriodicTaskBySourceIdAndType error,%v", err) | |||||
| return nil, err | |||||
| } | |||||
| return task, nil | |||||
| } | } | ||||
| if isHandled { | |||||
| log.Info("operate has been handled,opts=%+v", opts) | |||||
| return nil | |||||
| if err != nil && !models.IsErrRecordNotExist(err) { | |||||
| log.Error("operate is handled error,%v", err) | |||||
| return nil, err | |||||
| } | } | ||||
| //new reward operate record | //new reward operate record | ||||
| recordId, err := createPeriodicRewardOperateRecord(opts) | recordId, err := createPeriodicRewardOperateRecord(opts) | ||||
| if err != nil { | if err != nil { | ||||
| return err | |||||
| return nil, err | |||||
| } | } | ||||
| if err = NewRewardPeriodicTask(recordId, opts); err != nil { | if err = NewRewardPeriodicTask(recordId, opts); err != nil { | ||||
| updateAwardOperateRecordStatus(opts.SourceType.Name(), opts.RequestId, models.OperateStatusOperating, models.OperateStatusFailed) | |||||
| return err | |||||
| UpdateRewardRecordToFinalStatus(opts.SourceType.Name(), opts.RequestId, models.OperateStatusFailed) | |||||
| return nil, err | |||||
| } | } | ||||
| return nil | |||||
| task, err := models.GetPeriodicTaskBySourceIdAndType(opts.SourceType, opts.SourceId, opts.OperateType) | |||||
| if err != nil { | |||||
| log.Error("GetPeriodicTaskBySourceIdAndType error,%v", err) | |||||
| return nil, err | |||||
| } | |||||
| return task, nil | |||||
| } | } | ||||
| func StopPeriodicTaskAsyn(sourceType models.SourceType, sourceId string, operateType models.RewardOperateType) { | func StopPeriodicTaskAsyn(sourceType models.SourceType, sourceId string, operateType models.RewardOperateType) { | ||||
| @@ -6,6 +6,8 @@ import ( | |||||
| "code.gitea.io/gitea/modules/redis/redis_key" | "code.gitea.io/gitea/modules/redis/redis_key" | ||||
| "code.gitea.io/gitea/modules/redis/redis_lock" | "code.gitea.io/gitea/modules/redis/redis_lock" | ||||
| "code.gitea.io/gitea/modules/timeutil" | "code.gitea.io/gitea/modules/timeutil" | ||||
| "code.gitea.io/gitea/routers/repo" | |||||
| "errors" | |||||
| "fmt" | "fmt" | ||||
| "time" | "time" | ||||
| ) | ) | ||||
| @@ -46,33 +48,33 @@ func StartRewardTask() { | |||||
| } | } | ||||
| } | } | ||||
| func RunRewardTask(t models.RewardPeriodicTask, now time.Time) { | |||||
| func RunRewardTask(t models.RewardPeriodicTask, now time.Time) error { | |||||
| lock := redis_lock.NewDistributeLock(redis_key.RewardTaskRunningLock(t.ID)) | lock := redis_lock.NewDistributeLock(redis_key.RewardTaskRunningLock(t.ID)) | ||||
| isOk, _ := lock.LockWithWait(3*time.Second, 3*time.Second) | isOk, _ := lock.LockWithWait(3*time.Second, 3*time.Second) | ||||
| if !isOk { | if !isOk { | ||||
| log.Error("get RewardTaskRunningLock failed,t=%+v", t) | log.Error("get RewardTaskRunningLock failed,t=%+v", t) | ||||
| return | |||||
| return errors.New("get RewardTaskRunningLock failed") | |||||
| } | } | ||||
| defer lock.UnLock() | defer lock.UnLock() | ||||
| record, err := models.GetPointOperateRecordBySerialNo(t.OperateSerialNo) | record, err := models.GetPointOperateRecordBySerialNo(t.OperateSerialNo) | ||||
| if err != nil { | if err != nil { | ||||
| log.Error("RunRewardTask. GetPointOperateRecordBySerialNo error. %v", err) | log.Error("RunRewardTask. GetPointOperateRecordBySerialNo error. %v", err) | ||||
| return | |||||
| return errors.New("GetPointOperateRecordBySerialNo error") | |||||
| } | } | ||||
| if record.Status != models.OperateStatusOperating { | if record.Status != models.OperateStatusOperating { | ||||
| log.Info("RunRewardTask. operate record is finished,record=%+v", record) | log.Info("RunRewardTask. operate record is finished,record=%+v", record) | ||||
| return | |||||
| return nil | |||||
| } | } | ||||
| n, _ := countExecuteTimes(t, now) | n, _ := countExecuteTimes(t, now) | ||||
| if n == 0 { | if n == 0 { | ||||
| return | |||||
| return nil | |||||
| } | } | ||||
| //get operator | //get operator | ||||
| operator := GetOperator(models.GetRewardTypeInstance(record.RewardType)) | operator := GetOperator(models.GetRewardTypeInstance(record.RewardType)) | ||||
| if operator == nil { | if operator == nil { | ||||
| log.Error("RunRewardTask. operator of reward type is not exist") | log.Error("RunRewardTask. operator of reward type is not exist") | ||||
| return | |||||
| return errors.New("operator of reward type is not exist") | |||||
| } | } | ||||
| nextTime := t.NextExecuteTime | nextTime := t.NextExecuteTime | ||||
| for i := 0; int64(i) <= n; i++ { | for i := 0; int64(i) <= n; i++ { | ||||
| @@ -89,14 +91,20 @@ func RunRewardTask(t models.RewardPeriodicTask, now time.Time) { | |||||
| if err != nil { | if err != nil { | ||||
| log.Error("RunRewardTask.operator operate error.%v", err) | log.Error("RunRewardTask.operator operate error.%v", err) | ||||
| if models.IsErrInsufficientPointsBalance(err) { | if models.IsErrInsufficientPointsBalance(err) { | ||||
| StopCloudbrainTask(record) | |||||
| return | |||||
| task, err := models.GetCloudbrainByID(record.SourceId) | |||||
| if err != nil { | |||||
| log.Error("RunRewardTask GetCloudbrainByID error. %v", err) | |||||
| return err | |||||
| } | |||||
| repo.StopJobs([]*models.Cloudbrain{task}) | |||||
| return nil | |||||
| } | } | ||||
| return | |||||
| return nil | |||||
| } | } | ||||
| models.IncrRewardTaskSuccessCount(t, n, nextTime) | |||||
| models.IncrRewardTaskSuccessCount(t, 1, nextTime) | |||||
| nextTime = timeutil.TimeStamp(int64(nextTime) + t.IntervalSeconds) | nextTime = timeutil.TimeStamp(int64(nextTime) + t.IntervalSeconds) | ||||
| } | } | ||||
| return nil | |||||
| } | } | ||||
| @@ -111,8 +119,3 @@ func countExecuteTimes(t models.RewardPeriodicTask, now time.Time) (int64, timeu | |||||
| newNextTime := timeutil.TimeStamp(nextTime + n*interval) | newNextTime := timeutil.TimeStamp(nextTime + n*interval) | ||||
| return n, newNextTime | return n, newNextTime | ||||
| } | } | ||||
| func StopCloudbrainTask(r *models.RewardOperateRecord) { | |||||
| //todo | |||||
| } | |||||
| @@ -5,6 +5,7 @@ import ( | |||||
| "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/modules/redis/redis_lock" | "code.gitea.io/gitea/modules/redis/redis_lock" | ||||
| "code.gitea.io/gitea/modules/setting" | |||||
| "code.gitea.io/gitea/modules/util" | "code.gitea.io/gitea/modules/util" | ||||
| "encoding/json" | "encoding/json" | ||||
| "time" | "time" | ||||
| @@ -60,3 +61,20 @@ func InitAccount(userId int64) (*models.PointAccount, error) { | |||||
| return nil, nil | return nil, nil | ||||
| } | } | ||||
| //IsPointBalanceEnough check whether the user's point balance is bigger than task unit price | |||||
| func IsPointBalanceEnough(targetUserId int64, jobType string, resourceSpecId int) bool { | |||||
| if !setting.CloudBrainPaySwitch { | |||||
| return true | |||||
| } | |||||
| spec := models.GetResourceSpec(jobType, resourceSpecId) | |||||
| if spec == nil { | |||||
| return true | |||||
| } | |||||
| a, error := GetAccount(targetUserId) | |||||
| if error != nil { | |||||
| return false | |||||
| } | |||||
| return a.Balance >= spec.UnitPrice | |||||
| } | |||||
| @@ -1,9 +1,11 @@ | |||||
| package reward | package reward | ||||
| import "code.gitea.io/gitea/models" | |||||
| import ( | |||||
| "code.gitea.io/gitea/models" | |||||
| ) | |||||
| type RecordResponse struct { | type RecordResponse struct { | ||||
| Records []models.RewardOperateRecordShow | |||||
| Records []*models.RewardOperateRecordShow | |||||
| Total int64 | Total int64 | ||||
| PageSize int | PageSize int | ||||
| Page int | Page int | ||||
| @@ -14,9 +16,13 @@ func GetRewardRecordList(opts models.RewardRecordListOpts) (*RecordResponse, err | |||||
| if err != nil { | if err != nil { | ||||
| return nil, err | return nil, err | ||||
| } | } | ||||
| r := make([]models.RewardOperateRecordShow, 0) | |||||
| for _, v := range l { | |||||
| r = append(r, v.ToShow()) | |||||
| if len(l) == 0 { | |||||
| return &RecordResponse{Records: make([]*models.RewardOperateRecordShow, 0), Total: n, Page: opts.Page, PageSize: opts.PageSize}, nil | |||||
| } | } | ||||
| return &RecordResponse{Records: r, Total: n, Page: opts.Page, PageSize: opts.PageSize}, nil | |||||
| result, err := l.ToShow() | |||||
| if err != nil { | |||||
| return nil, err | |||||
| } | |||||
| return &RecordResponse{Records: result, Total: n, Page: opts.Page, PageSize: opts.PageSize}, nil | |||||
| } | } | ||||
| @@ -3,7 +3,6 @@ package task | |||||
| import ( | import ( | ||||
| "code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
| "code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
| "code.gitea.io/gitea/modules/util" | |||||
| "code.gitea.io/gitea/services/reward" | "code.gitea.io/gitea/services/reward" | ||||
| "code.gitea.io/gitea/services/reward/limiter" | "code.gitea.io/gitea/services/reward/limiter" | ||||
| "fmt" | "fmt" | ||||
| @@ -55,9 +54,7 @@ func accomplish(action models.Action) error { | |||||
| } | } | ||||
| //add log | //add log | ||||
| logId := util.UUID() | |||||
| _, err = models.InsertTaskAccomplishLog(&models.TaskAccomplishLog{ | _, err = models.InsertTaskAccomplishLog(&models.TaskAccomplishLog{ | ||||
| LogId: logId, | |||||
| ConfigId: config.ID, | ConfigId: config.ID, | ||||
| TaskCode: config.TaskCode, | TaskCode: config.TaskCode, | ||||
| UserId: userId, | UserId: userId, | ||||
| @@ -70,14 +67,14 @@ func accomplish(action models.Action) error { | |||||
| //reward | //reward | ||||
| reward.Operate(&models.RewardOperateContext{ | reward.Operate(&models.RewardOperateContext{ | ||||
| SourceType: models.SourceTypeAccomplishTask, | SourceType: models.SourceTypeAccomplishTask, | ||||
| SourceId: logId, | |||||
| SourceId: fmt.Sprint(action.ID), | |||||
| Tittle: config.Tittle, | Tittle: config.Tittle, | ||||
| Reward: models.Reward{ | Reward: models.Reward{ | ||||
| Amount: config.AwardAmount, | Amount: config.AwardAmount, | ||||
| Type: models.GetRewardTypeInstance(config.AwardType), | Type: models.GetRewardTypeInstance(config.AwardType), | ||||
| }, | }, | ||||
| TargetUserId: userId, | TargetUserId: userId, | ||||
| RequestId: logId, | |||||
| RequestId: fmt.Sprint(action.ID), | |||||
| OperateType: models.OperateTypeIncrease, | OperateType: models.OperateTypeIncrease, | ||||
| RejectPolicy: models.FillUp, | RejectPolicy: models.FillUp, | ||||
| }) | }) | ||||