作者 郑周

1. 项目启动,增加并发锁

... ... @@ -2,6 +2,7 @@ package service
import (
"fmt"
"gitlab.fjmaimaimai.com/allied-creation/performance/pkg/infrastructure/xredis"
"strconv"
"strings"
"time"
... ... @@ -482,6 +483,15 @@ func (rs *EvaluationProjectService) List(in *command.QueryProjectCommand) (inter
}
func (rs *EvaluationProjectService) Activate(in *command.ActivateProjectCommand) (interface{}, error) {
lock := xredis.NewLockProjectId(int(in.Id))
err := lock.Lock()
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
defer func() {
lock.UnLock()
}()
transactionContext, err := factory.ValidateStartTransaction(in)
if err != nil {
return nil, err
... ... @@ -562,56 +572,61 @@ func (rs *EvaluationProjectService) Activate(in *command.ActivateProjectCommand)
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
now := time.Now().Local()
year, month, day := now.Date()
nowO := time.Date(year, month, day, 0, 0, 0, 0, time.Local) // 当前时间0点0分0秒时刻
tasks, err := taskRepository.Find(map[string]interface{}{"projectId": project.Id})
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
if len(tasks) == 0 {
now := time.Now().Local()
year, month, day := now.Date()
nowO := time.Date(year, month, day, 0, 0, 0, 0, time.Local) // 当前时间0点0分0秒时刻
for i := range project.Template.LinkNodes {
node := project.Template.LinkNodes[i]
task := &domain.NodeTask{
Id: 0,
CompanyId: project.CompanyId,
CycleId: project.CycleId,
ProjectId: project.Id,
NodeId: node.Id,
NodeType: node.Type,
NodeName: node.Name,
NodeDescribe: node.Describe,
NodeSort: i + 1,
TimeStart: node.TimeStart,
TimeEnd: node.TimeEnd,
KpiCycle: node.KpiCycle,
}
for i := range project.Template.LinkNodes {
node := project.Template.LinkNodes[i]
task := &domain.NodeTask{
Id: 0,
CompanyId: project.CompanyId,
CycleId: project.CycleId,
ProjectId: project.Id,
NodeId: node.Id,
NodeType: node.Type,
NodeName: node.Name,
NodeDescribe: node.Describe,
NodeSort: i + 1,
TimeStart: node.TimeStart,
TimeEnd: node.TimeEnd,
KpiCycle: node.KpiCycle,
}
// 环节起始和截止本地时间
startLocal := task.TimeStart.Local()
sY, sM, sD := startLocal.Date()
startLocal = time.Date(sY, sM, sD, 0, 0, 0, 0, time.Local) // 开始时间以0点开始计算
endLocal := task.TimeEnd.Local()
// 在当前时间之前,则计算下一个周期时间
if startLocal.Before(nowO) {
nextTime := utils.NextTime(nowO, startLocal, node.KpiCycle)
task.NextSentAt = &nextTime
} else {
task.NextSentAt = &startLocal
}
// 如果超出截至时间,则周期置空
if task.NextSentAt.After(endLocal) {
task.NextSentAt = nil
// 环节起始和截止本地时间
startLocal := task.TimeStart.Local()
sY, sM, sD := startLocal.Date()
startLocal = time.Date(sY, sM, sD, 0, 0, 0, 0, time.Local) // 开始时间以0点开始计算
endLocal := task.TimeEnd.Local()
// 在当前时间之前,则计算下一个周期时间
if startLocal.Before(nowO) {
nextTime := utils.NextTime(nowO, startLocal, node.KpiCycle)
task.NextSentAt = &nextTime
} else {
task.NextSentAt = &startLocal
}
// 如果超出截至时间,则周期置空
if task.NextSentAt.After(endLocal) {
task.NextSentAt = nil
}
_, err := taskRepository.Insert(task)
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
}
_, err := taskRepository.Insert(task)
err = rs.generateEvaluationItemUsed(transactionContext, project)
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
}
err = rs.generateEvaluationItemUsed(transactionContext, project)
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
if err := transactionContext.CommitTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
... ...
package xredis
import (
"fmt"
"github.com/go-redsync/redsync/v4"
)
type LockProjectId struct {
m *redsync.Mutex
}
func NewLockProjectId(id int) *LockProjectId {
key := fmt.Sprintf("performance:project_id:%d", id)
return &LockProjectId{
m: rsync.NewMutex(key),
}
}
func (lk *LockProjectId) Lock() error {
return lk.m.Lock()
}
func (lk *LockProjectId) UnLock() (bool, error) {
return lk.m.Unlock()
}
... ...