@@ -91,6 +91,23 @@ type Action struct { | |||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||
} | |||
type ActionShow struct { | |||
UserID int64 | |||
OpType ActionType | |||
ActUserID int64 | |||
ActUser *UserShow | |||
RepoID int64 | |||
Repo *RepositoryShow | |||
CommentID int64 | |||
Comment *Comment `xorm:"-"` | |||
IsDeleted bool `xorm:"INDEX NOT NULL DEFAULT false"` | |||
RefName string | |||
IsPrivate bool `xorm:"INDEX NOT NULL DEFAULT false"` | |||
IsTransformed bool `xorm:"INDEX NOT NULL DEFAULT false"` | |||
Content string `xorm:"TEXT"` | |||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||
} | |||
// GetOpType gets the ActionType of this action. | |||
func (a *Action) GetOpType() ActionType { | |||
return a.OpType | |||
@@ -237,6 +237,12 @@ type Repository struct { | |||
LowerAlias string `xorm:"INDEX"` | |||
} | |||
type RepositoryShow struct { | |||
Name string | |||
RepoType RepoType | |||
Alias string | |||
} | |||
// SanitizedOriginalURL returns a sanitized OriginalURL | |||
func (repo *Repository) SanitizedOriginalURL() string { | |||
if repo.OriginalURL == "" { | |||
@@ -213,21 +213,22 @@ func (l *RewardRecordList) GetRewardRecordCloudbrainTask() (map[string]Cloudbrai | |||
} | |||
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"` | |||
FinishedUnix timeutil.TimeStamp `xorm:"INDEX"` | |||
ID int64 `xorm:"pk autoincr"` | |||
SerialNo string `xorm:"INDEX NOT NULL"` | |||
UserId int64 `xorm:"INDEX NOT NULL"` | |||
Amount int64 `xorm:"NOT NULL"` | |||
LossAmount int64 | |||
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"` | |||
LastOperateUnix timeutil.TimeStamp `xorm:"INDEX"` | |||
} | |||
type AdminRewardOperateReq struct { | |||
@@ -240,27 +241,31 @@ type AdminRewardOperateReq struct { | |||
func (r RewardOperateRecord) ToShow() RewardOperateRecordShow { | |||
return RewardOperateRecordShow{ | |||
SerialNo: r.SerialNo, | |||
Date: r.CreatedUnix, | |||
OperateType: r.OperateType, | |||
Amount: r.Amount, | |||
Remark: r.Remark, | |||
Status: r.Status, | |||
SourceType: r.SourceType, | |||
SerialNo: r.SerialNo, | |||
Date: r.CreatedUnix, | |||
OperateType: r.OperateType, | |||
Amount: r.Amount, | |||
Remark: r.Remark, | |||
Status: r.Status, | |||
SourceType: r.SourceType, | |||
LastOperateTask: r.LastOperateUnix, | |||
LossAmount: r.LossAmount, | |||
} | |||
} | |||
type RewardOperateRecordShow struct { | |||
SerialNo string | |||
Date timeutil.TimeStamp | |||
Status string | |||
OperateType string | |||
Amount int64 | |||
Remark string | |||
SourceType string | |||
Action Action | |||
Cloudbrain Cloudbrain | |||
AdminLog RewardAdminLog | |||
SerialNo string | |||
Date timeutil.TimeStamp | |||
Status string | |||
OperateType string | |||
Amount int64 | |||
LossAmount int64 | |||
Remark string | |||
SourceType string | |||
LastOperateTask timeutil.TimeStamp | |||
Action Action | |||
Cloudbrain Cloudbrain | |||
AdminLog RewardAdminLog | |||
} | |||
func getPointOperateRecord(tl *RewardOperateRecord) (*RewardOperateRecord, error) { | |||
@@ -295,10 +300,10 @@ func InsertRewardOperateRecord(tl *RewardOperateRecord) (int64, error) { | |||
func UpdateRewardRecordToFinalStatus(sourceType, requestId, newStatus string) (int64, error) { | |||
r := &RewardOperateRecord{ | |||
Status: newStatus, | |||
FinishedUnix: timeutil.TimeStampNow(), | |||
Status: newStatus, | |||
LastOperateUnix: timeutil.TimeStampNow(), | |||
} | |||
return x.Cols("status", "finished_unix").Where("source_type=? and request_id=? and status=?", sourceType, requestId, OperateStatusOperating).Update(r) | |||
return x.Cols("status", "last_operate_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) { | |||
@@ -326,6 +331,7 @@ type RewardOperateContext struct { | |||
OperateType RewardOperateType | |||
RejectPolicy LimiterRejectPolicy | |||
PermittedNegative bool | |||
LossAmount int64 | |||
} | |||
type Reward struct { | |||
@@ -77,7 +77,7 @@ func IncrRewardTaskSuccessCount(t RewardPeriodicTask, count int64, nextTime time | |||
sess.Rollback() | |||
return err | |||
} | |||
_, err = sess.Exec("update reward_operate_record set amount = amount + ? ,updated_unix = ? where serial_no = ?", t.Amount, timeutil.TimeStampNow(), t.OperateSerialNo) | |||
_, err = sess.Exec("update reward_operate_record set amount = amount + ? ,updated_unix = ? ,last_operate_unix = ? where serial_no = ?", t.Amount, timeutil.TimeStampNow(), timeutil.TimeStampNow(), t.OperateSerialNo) | |||
if err != nil { | |||
sess.Rollback() | |||
return err | |||
@@ -186,6 +186,10 @@ type User struct { | |||
WechatBindUnix timeutil.TimeStamp | |||
} | |||
type UserShow struct { | |||
Name string | |||
} | |||
// SearchOrganizationsOptions options to filter organizations | |||
type SearchOrganizationsOptions struct { | |||
ListOptions | |||
@@ -59,7 +59,7 @@ func StartCloudbrainPointDeductTask() { | |||
}() | |||
log.Debug("try to run CloudbrainPointDeductTask") | |||
end := time.Now() | |||
start := end.Add(-5 * time.Minute) | |||
start := end.Add(-30 * time.Minute) | |||
if firstTimeFlag { | |||
//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 | |||
@@ -76,30 +76,35 @@ func StartCloudbrainPointDeductTask() { | |||
return | |||
} | |||
for _, t := range taskList { | |||
//初始化 period_task 和 operate_record | |||
if int64(t.StartTime) > end.Unix() || int64(t.StartTime) < start.Unix() { | |||
continue | |||
} | |||
DeductPoint4Cloudbrain(t, end) | |||
} | |||
} | |||
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 | |||
} | |||
func DeductPoint4Cloudbrain(t models.Cloudbrain, now time.Time) error { | |||
if int64(t.EndTime) <= end.Unix() && int64(t.EndTime) >= start.Unix() { | |||
endTime := time.Unix(int64(t.EndTime), 0) | |||
RunRewardTask(*task, endTime) | |||
models.StopPeriodicTask(task.ID, task.OperateSerialNo, endTime) | |||
} else { | |||
RunRewardTask(*task, end) | |||
} | |||
if t.StartTime == 0 { | |||
return nil | |||
} | |||
task, err := StartAndGetCloudBrainPointDeductTask(t) | |||
if err != nil { | |||
log.Error("run cloudbrain point deduct task error,err=%v", err) | |||
return err | |||
} | |||
if task == nil { | |||
return nil | |||
} | |||
if task.Status == models.PeriodicTaskStatusFinished { | |||
log.Info("Periodic task is finished") | |||
return nil | |||
} | |||
if t.EndTime > 0 { | |||
endTime := time.Unix(int64(t.EndTime), 0) | |||
RunRewardTask(*task, endTime) | |||
models.StopPeriodicTask(task.ID, task.OperateSerialNo, endTime) | |||
} else { | |||
RunRewardTask(*task, now) | |||
} | |||
return nil | |||
} |
@@ -35,7 +35,7 @@ func GetRewardOperation(since, until timeutil.TimeStamp) []models.UserRewardOper | |||
json.Unmarshal([]byte(v), &t) | |||
r = append(r, models.UserRewardOperation{ | |||
UserId: t.UserId, | |||
Msg: GetRewardOperateMsg(t), | |||
Msg: v, | |||
}) | |||
} | |||
redis_client.ZRemRangeByScore(redis_key.RewardOperateNotification(), float64(since), float64(until)) | |||
@@ -118,6 +118,7 @@ func initRewardOperateRecord(ctx *models.RewardOperateContext) (string, error) { | |||
record := &models.RewardOperateRecord{ | |||
UserId: ctx.TargetUserId, | |||
Amount: ctx.Reward.Amount, | |||
LossAmount: ctx.LossAmount, | |||
RewardType: ctx.Reward.Type.Name(), | |||
SourceType: ctx.SourceType.Name(), | |||
SourceId: ctx.SourceId, | |||
@@ -77,7 +77,7 @@ func RunRewardTask(t models.RewardPeriodicTask, now time.Time) error { | |||
return errors.New("operator of reward type is not exist") | |||
} | |||
nextTime := t.NextExecuteTime | |||
for i := 0; int64(i) <= n; i++ { | |||
for i := 1; int64(i) <= n; i++ { | |||
err = operator.Operate(&models.RewardOperateContext{ | |||
SourceType: models.SourceTypeRunCloudbrainTask, | |||
SourceId: t.OperateSerialNo, | |||
@@ -97,6 +97,7 @@ func RunRewardTask(t models.RewardPeriodicTask, now time.Time) error { | |||
return err | |||
} | |||
repo.StopJobs([]*models.Cloudbrain{task}) | |||
models.StopPeriodicTask(task.ID, t.OperateSerialNo, time.Now()) | |||
return nil | |||
} | |||
return nil | |||
@@ -9,12 +9,9 @@ import ( | |||
"code.gitea.io/gitea/services/reward/limiter" | |||
"code.gitea.io/gitea/services/reward/point/account" | |||
"errors" | |||
"fmt" | |||
"time" | |||
) | |||
const LossMsg = "达到奖励上限,应得%d积分,实得%d积分" | |||
type PointOperator struct { | |||
} | |||
@@ -24,7 +21,7 @@ func (operator *PointOperator) IsLimited(ctx *models.RewardOperateContext) error | |||
return err | |||
} | |||
if realAmount < ctx.Reward.Amount { | |||
ctx.Remark = models.AppendRemark(ctx.Remark, fmt.Sprintf(LossMsg, ctx.Reward.Amount, realAmount)) | |||
ctx.LossAmount = ctx.Reward.Amount - realAmount | |||
ctx.Reward.Amount = realAmount | |||
} | |||
return nil | |||
@@ -49,7 +46,7 @@ func (operator *PointOperator) Operate(ctx *models.RewardOperateContext) error { | |||
} else if ctx.OperateType == models.OperateTypeDecrease { | |||
if !ctx.PermittedNegative && na.Balance < ctx.Reward.Amount { | |||
log.Info("account balance is not enough,ctx=%v", ctx) | |||
return &models.ErrInsufficientPointsBalance{} | |||
return models.ErrInsufficientPointsBalance{} | |||
} | |||
err = na.Decrease(ctx.Reward.Amount, ctx.SourceId) | |||
} | |||