task locking
parent
8bade7992d
commit
cc3758c8d3
|
@ -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,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
2
main.go
2
main.go
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -40,7 +40,7 @@ type GroupTaskSteps struct {
|
||||||
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
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
isAlreadyInList := cache.AddLockedGroupTaskStep(structs.LockedGroupTaskSteps{
|
||||||
|
LockedByUserId: receivedMessage.Body["lockedByUserId"].(string),
|
||||||
|
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{
|
socketclients.BroadcastMessageExceptUserSessionId(data.Conn.Locals("sessionId").(string), structs.SendSocketMessage{
|
||||||
Cmd: utils.SentCmdTaskLocked,
|
Cmd: utils.SentCmdTaskLocked,
|
||||||
Body: receivedMessage.Body,
|
Body: receivedMessage.Body,
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Reference in New Issue