task locking

main
alex 2023-05-27 22:36:16 +02:00
parent 8bade7992d
commit cc3758c8d3
7 changed files with 114 additions and 19 deletions

View File

@ -278,3 +278,28 @@ func GetCategoryGroupTaskByCategoryAndGroupId(category string, groupId string) s
return structs.Group{} return structs.Group{}
} }
func StartUnlockLockedGroupTaskStepsTicker() {
ticker := time.NewTicker(1 * time.Second)
for _ = range ticker.C {
for index, taskStep := range cache.GetLockedGroupTaskSteps() {
if time.Since(taskStep.LockedAt).Seconds() > 3 {
log.Debug().Msgf("Unlocked task step", index)
cache.RemoveLockedGroupTaskStep(index)
socketclients.BroadcastMessageExceptUserSessionId(taskStep.LockedByUserSession,
structs.SendSocketMessage{
Cmd: utils.SentCmdTaskUnlocked,
Body: struct {
GroupTaskId string
Step uint8
}{
GroupTaskId: taskStep.GroupTaskId,
Step: taskStep.Step,
},
})
}
}
}
}

View File

@ -79,6 +79,8 @@ func main() {
go socketserver.RunHub() go socketserver.RunHub()
socketserver.WebSocketServer(app) socketserver.WebSocketServer(app)
go grouptasks.StartUnlockLockedGroupTaskStepsTicker()
app.Listen(config.Cfg.Host + ":" + config.Cfg.Port) app.Listen(config.Cfg.Host + ":" + config.Cfg.Port)
} }

View File

@ -6,16 +6,16 @@ import (
"sync" "sync"
) )
var CategoryGroups []structs.CategoryGroup var categoryGroups []structs.CategoryGroup
var cgMu sync.RWMutex var cgMu sync.RWMutex
func AddCategoryGroup(group structs.Group) { func AddCategoryGroup(group structs.Group) {
cgMu.Lock() cgMu.Lock()
defer cgMu.Unlock() defer cgMu.Unlock()
for index, categoryGroup := range CategoryGroups { for index, categoryGroup := range categoryGroups {
if categoryGroup.Category == group.Category { if categoryGroup.Category == group.Category {
CategoryGroups[index].Groups = append(CategoryGroups[index].Groups, group) categoryGroups[index].Groups = append(categoryGroups[index].Groups, group)
return return
} }
} }
@ -26,7 +26,7 @@ func AddCategoryGroup(group structs.Group) {
categoryGroup.Groups = append(categoryGroup.Groups, group) categoryGroup.Groups = append(categoryGroup.Groups, group)
CategoryGroups = append(CategoryGroups, categoryGroup) categoryGroups = append(categoryGroups, categoryGroup)
} }
func RemoveAllCategoryGroupsByCategory(category string) { func RemoveAllCategoryGroupsByCategory(category string) {
@ -35,7 +35,7 @@ func RemoveAllCategoryGroupsByCategory(category string) {
cgMu.Lock() cgMu.Lock()
defer cgMu.Unlock() defer cgMu.Unlock()
CategoryGroups = append(CategoryGroups[:index], CategoryGroups[index+1:]...) categoryGroups = append(categoryGroups[:index], categoryGroups[index+1:]...)
} }
} }
} }
@ -55,5 +55,5 @@ func GetCategoryGroups() []structs.CategoryGroup {
cgMu.RLock() cgMu.RLock()
defer cgMu.RUnlock() defer cgMu.RUnlock()
return CategoryGroups return categoryGroups
} }

44
modules/cache/lockedgrouptasksteps.go vendored Normal file
View File

@ -0,0 +1,44 @@
package cache
import (
"janex/admin-dashboard-backend/modules/structs"
"sync"
"time"
)
var lockedGroupTaskSteps []*structs.LockedGroupTaskSteps
var lgtMu sync.RWMutex
func AddLockedGroupTaskStep(lockedGroupTaskStep structs.LockedGroupTaskSteps) (IsAlreadyInList bool) {
lgtMu.Lock()
var isAlreadyInList = false
for _, step := range lockedGroupTaskSteps {
if step.GroupTaskId == lockedGroupTaskStep.GroupTaskId &&
step.LockedByUserId == lockedGroupTaskStep.LockedByUserId {
isAlreadyInList = true
step.LockedAt = time.Now()
break
}
}
if !isAlreadyInList {
lockedGroupTaskSteps = append(lockedGroupTaskSteps, &lockedGroupTaskStep)
}
lgtMu.Unlock()
return isAlreadyInList
}
func RemoveLockedGroupTaskStep(i int) {
lockedGroupTaskSteps = append(lockedGroupTaskSteps[:i], lockedGroupTaskSteps[i+1:]...)
}
func GetLockedGroupTaskSteps() []*structs.LockedGroupTaskSteps {
lgtMu.RLock()
defer lgtMu.RUnlock()
return lockedGroupTaskSteps
}

View File

@ -31,16 +31,16 @@ type GroupTasks struct {
} }
type GroupTaskSteps struct { type GroupTaskSteps struct {
Id string Id string
GroupTasksId string GroupTasksId string
CreatorUserId string CreatorUserId string
Step uint8 Step uint8
Status uint8 Status uint8
Log string `gorm:"type:text"` Log string `gorm:"type:text"`
Inputs string `gorm:"type:json"` Inputs string `gorm:"type:json"`
StartedAt time.Time StartedAt time.Time
EndedAt time.Time EndedAt time.Time
Locked bool `gorm:"-"` // used by the web client to ensure that only one user can edit the input value LockedByUserId string `gorm:"-"` // used by the web client to ensure that only one user can edit the input value
} }
// read from file structure // read from file structure
@ -79,3 +79,13 @@ type TaskParameter struct {
DisplayName string `json:"displayName"` DisplayName string `json:"displayName"`
Global bool `json:"global"` Global bool `json:"global"`
} }
// used for ui when a user is writing into input field to lock the task step for other users
type LockedGroupTaskSteps struct {
LockedByUserId string
LockedByUserSession string // user session is needed to prevent sending the unlocking message to the user who are writing
GroupTaskId string
Step uint8
LockedAt time.Time
}

View File

@ -17,6 +17,8 @@ const (
HeaderXAuthorization = "X-Authorization" HeaderXAuthorization = "X-Authorization"
MaxAvatarSize = 5 * 1024 * 1024 // 5 MB MaxAvatarSize = 5 * 1024 * 1024 // 5 MB
GroupTaskLockedTime = 3 // seconds - need to be equal with web
) )
// commands sent to web clients // commands sent to web clients
@ -37,6 +39,7 @@ const (
SentCmdScanResult = 14 SentCmdScanResult = 14
SentCmdUpdateScannerLastUsed = 15 SentCmdUpdateScannerLastUsed = 15
SentCmdTaskLocked = 16 SentCmdTaskLocked = 16
SentCmdTaskUnlocked = 17
) )
// commands received from web clients // commands received from web clients

View File

@ -157,10 +157,21 @@ func RunHub() {
case utils.ReceivedCmdTaskLocking: case utils.ReceivedCmdTaskLocking:
log.Info().Msgf("task locking %s", receivedMessage.Body) log.Info().Msgf("task locking %s", receivedMessage.Body)
socketclients.BroadcastMessageExceptUserSessionId(data.Conn.Locals("sessionId").(string), structs.SendSocketMessage{ isAlreadyInList := cache.AddLockedGroupTaskStep(structs.LockedGroupTaskSteps{
Cmd: utils.SentCmdTaskLocked, LockedByUserId: receivedMessage.Body["lockedByUserId"].(string),
Body: receivedMessage.Body, LockedByUserSession: data.Conn.Locals("sessionId").(string),
GroupTaskId: receivedMessage.Body["groupTaskId"].(string),
Step: uint8(receivedMessage.Body["step"].(float64)),
LockedAt: time.Now(),
}) })
if !isAlreadyInList {
socketclients.BroadcastMessageExceptUserSessionId(data.Conn.Locals("sessionId").(string), structs.SendSocketMessage{
Cmd: utils.SentCmdTaskLocked,
Body: receivedMessage.Body,
})
}
break break
default: default: