task locking
parent
8bade7992d
commit
cc3758c8d3
|
@ -278,3 +278,28 @@ func GetCategoryGroupTaskByCategoryAndGroupId(category string, groupId string) s
|
|||
|
||||
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()
|
||||
socketserver.WebSocketServer(app)
|
||||
|
||||
go grouptasks.StartUnlockLockedGroupTaskStepsTicker()
|
||||
|
||||
app.Listen(config.Cfg.Host + ":" + config.Cfg.Port)
|
||||
}
|
||||
|
||||
|
|
|
@ -6,16 +6,16 @@ import (
|
|||
"sync"
|
||||
)
|
||||
|
||||
var CategoryGroups []structs.CategoryGroup
|
||||
var categoryGroups []structs.CategoryGroup
|
||||
var cgMu sync.RWMutex
|
||||
|
||||
func AddCategoryGroup(group structs.Group) {
|
||||
cgMu.Lock()
|
||||
defer cgMu.Unlock()
|
||||
|
||||
for index, categoryGroup := range CategoryGroups {
|
||||
for index, categoryGroup := range categoryGroups {
|
||||
if categoryGroup.Category == group.Category {
|
||||
CategoryGroups[index].Groups = append(CategoryGroups[index].Groups, group)
|
||||
categoryGroups[index].Groups = append(categoryGroups[index].Groups, group)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ func AddCategoryGroup(group structs.Group) {
|
|||
|
||||
categoryGroup.Groups = append(categoryGroup.Groups, group)
|
||||
|
||||
CategoryGroups = append(CategoryGroups, categoryGroup)
|
||||
categoryGroups = append(categoryGroups, categoryGroup)
|
||||
}
|
||||
|
||||
func RemoveAllCategoryGroupsByCategory(category string) {
|
||||
|
@ -35,7 +35,7 @@ func RemoveAllCategoryGroupsByCategory(category string) {
|
|||
cgMu.Lock()
|
||||
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()
|
||||
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
|
||||
}
|
|
@ -31,16 +31,16 @@ type GroupTasks struct {
|
|||
}
|
||||
|
||||
type GroupTaskSteps struct {
|
||||
Id string
|
||||
GroupTasksId string
|
||||
CreatorUserId string
|
||||
Step uint8
|
||||
Status uint8
|
||||
Log string `gorm:"type:text"`
|
||||
Inputs string `gorm:"type:json"`
|
||||
StartedAt time.Time
|
||||
EndedAt time.Time
|
||||
Locked bool `gorm:"-"` // used by the web client to ensure that only one user can edit the input value
|
||||
Id string
|
||||
GroupTasksId string
|
||||
CreatorUserId string
|
||||
Step uint8
|
||||
Status uint8
|
||||
Log string `gorm:"type:text"`
|
||||
Inputs string `gorm:"type:json"`
|
||||
StartedAt time.Time
|
||||
EndedAt time.Time
|
||||
LockedByUserId string `gorm:"-"` // used by the web client to ensure that only one user can edit the input value
|
||||
}
|
||||
|
||||
// read from file structure
|
||||
|
@ -79,3 +79,13 @@ type TaskParameter struct {
|
|||
DisplayName string `json:"displayName"`
|
||||
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"
|
||||
|
||||
MaxAvatarSize = 5 * 1024 * 1024 // 5 MB
|
||||
|
||||
GroupTaskLockedTime = 3 // seconds - need to be equal with web
|
||||
)
|
||||
|
||||
// commands sent to web clients
|
||||
|
@ -37,6 +39,7 @@ const (
|
|||
SentCmdScanResult = 14
|
||||
SentCmdUpdateScannerLastUsed = 15
|
||||
SentCmdTaskLocked = 16
|
||||
SentCmdTaskUnlocked = 17
|
||||
)
|
||||
|
||||
// commands received from web clients
|
||||
|
|
|
@ -157,10 +157,21 @@ func RunHub() {
|
|||
case utils.ReceivedCmdTaskLocking:
|
||||
log.Info().Msgf("task locking %s", receivedMessage.Body)
|
||||
|
||||
socketclients.BroadcastMessageExceptUserSessionId(data.Conn.Locals("sessionId").(string), structs.SendSocketMessage{
|
||||
Cmd: utils.SentCmdTaskLocked,
|
||||
Body: 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{
|
||||
Cmd: utils.SentCmdTaskLocked,
|
||||
Body: receivedMessage.Body,
|
||||
})
|
||||
}
|
||||
|
||||
break
|
||||
|
||||
default:
|
||||
|
|
Loading…
Reference in New Issue