feat: activity 并发安全优化

This commit is contained in:
kercylan98 2023-11-23 19:55:53 +08:00
parent 193635c1a9
commit 7c2a825408
3 changed files with 39 additions and 2 deletions

View File

@ -115,7 +115,7 @@ type Activity[Type, ID generic.Basic] struct {
tickerKey string // 定时器 key tickerKey string // 定时器 key
retention time.Duration // 活动数据保留时间 retention time.Duration // 活动数据保留时间
retentionKey string // 保留定时器 key retentionKey string // 保留定时器 key
mutex sync.Mutex // 互斥锁 mutex sync.RWMutex
getLastNewDayTime func() time.Time // 获取上次新的一天的时间 getLastNewDayTime func() time.Time // 获取上次新的一天的时间
setLastNewDayTime func(time.Time) // 设置上次新的一天的时间 setLastNewDayTime func(time.Time) // 设置上次新的一天的时间

View File

@ -1,6 +1,9 @@
package activity package activity
import "github.com/kercylan98/minotaur/utils/generic" import (
"github.com/kercylan98/minotaur/utils/generic"
"sync"
)
type none byte type none byte
@ -52,59 +55,81 @@ type Controller[Type, ID generic.Basic, Data any, EntityID generic.Basic, Entity
entityInitializer func(activityType Type, activityId ID, data map[ID]*DataMeta[Data], entityData map[ID]map[EntityID]*EntityDataMeta[EntityData]) // 实体数据初始化器 entityInitializer func(activityType Type, activityId ID, data map[ID]*DataMeta[Data], entityData map[ID]map[EntityID]*EntityDataMeta[EntityData]) // 实体数据初始化器
globalData map[ID]*DataMeta[Data] // 全局数据 globalData map[ID]*DataMeta[Data] // 全局数据
entityData map[ID]map[EntityID]*EntityDataMeta[EntityData] // 实体数据 entityData map[ID]map[EntityID]*EntityDataMeta[EntityData] // 实体数据
mutex sync.RWMutex
} }
// GetGlobalData 获取特定活动全局数据 // GetGlobalData 获取特定活动全局数据
func (slf *Controller[Type, ID, Data, EntityID, EntityData]) GetGlobalData(activityId ID) Data { func (slf *Controller[Type, ID, Data, EntityID, EntityData]) GetGlobalData(activityId ID) Data {
slf.globalDataLoader(activityId) slf.globalDataLoader(activityId)
slf.mutex.RLock()
defer slf.mutex.RUnlock()
return slf.globalData[activityId].Data return slf.globalData[activityId].Data
} }
// GetEntityData 获取特定活动实体数据 // GetEntityData 获取特定活动实体数据
func (slf *Controller[Type, ID, Data, EntityID, EntityData]) GetEntityData(activityId ID, entityId EntityID) EntityData { func (slf *Controller[Type, ID, Data, EntityID, EntityData]) GetEntityData(activityId ID, entityId EntityID) EntityData {
slf.entityDataLoader(activityId, entityId) slf.entityDataLoader(activityId, entityId)
slf.mutex.RLock()
defer slf.mutex.RUnlock()
return slf.entityData[activityId][entityId].Data return slf.entityData[activityId][entityId].Data
} }
// GetAllEntityData 获取特定活动所有实体数据 // GetAllEntityData 获取特定活动所有实体数据
func (slf *Controller[Type, ID, Data, EntityID, EntityData]) GetAllEntityData(activityId ID) map[EntityID]EntityData { func (slf *Controller[Type, ID, Data, EntityID, EntityData]) GetAllEntityData(activityId ID) map[EntityID]EntityData {
var entities = make(map[EntityID]EntityData) var entities = make(map[EntityID]EntityData)
slf.mutex.RLock()
for k, v := range slf.entityData[activityId] { for k, v := range slf.entityData[activityId] {
entities[k] = v.Data entities[k] = v.Data
} }
slf.mutex.RUnlock()
return entities return entities
} }
// IsOpen 活动是否开启 // IsOpen 活动是否开启
func (slf *Controller[Type, ID, Data, EntityID, EntityData]) IsOpen(activityId ID) bool { func (slf *Controller[Type, ID, Data, EntityID, EntityData]) IsOpen(activityId ID) bool {
slf.mutex.RLock()
activity, exist := slf.activities[activityId] activity, exist := slf.activities[activityId]
slf.mutex.RUnlock()
if !exist { if !exist {
return false return false
} }
activity.mutex.RLock()
defer activity.mutex.RUnlock()
return activity.state == stateStarted return activity.state == stateStarted
} }
// IsShow 活动是否展示 // IsShow 活动是否展示
func (slf *Controller[Type, ID, Data, EntityID, EntityData]) IsShow(activityId ID) bool { func (slf *Controller[Type, ID, Data, EntityID, EntityData]) IsShow(activityId ID) bool {
slf.mutex.RLock()
activity, exist := slf.activities[activityId] activity, exist := slf.activities[activityId]
slf.mutex.RUnlock()
if !exist { if !exist {
return false return false
} }
activity.mutex.RLock()
defer activity.mutex.RUnlock()
return activity.state == stateUpcoming || (activity.state == stateEnded && activity.tl.HasState(stateExtendedShowEnded)) return activity.state == stateUpcoming || (activity.state == stateEnded && activity.tl.HasState(stateExtendedShowEnded))
} }
// IsOpenOrShow 活动是否开启或展示 // IsOpenOrShow 活动是否开启或展示
func (slf *Controller[Type, ID, Data, EntityID, EntityData]) IsOpenOrShow(activityId ID) bool { func (slf *Controller[Type, ID, Data, EntityID, EntityData]) IsOpenOrShow(activityId ID) bool {
slf.mutex.RLock()
activity, exist := slf.activities[activityId] activity, exist := slf.activities[activityId]
slf.mutex.RUnlock()
if !exist { if !exist {
return false return false
} }
activity.mutex.RLock()
defer activity.mutex.RUnlock()
return activity.state == stateStarted || activity.state == stateUpcoming || (activity.state == stateEnded && activity.tl.HasState(stateExtendedShowEnded)) return activity.state == stateStarted || activity.state == stateUpcoming || (activity.state == stateEnded && activity.tl.HasState(stateExtendedShowEnded))
} }
// Refresh 刷新活动 // Refresh 刷新活动
func (slf *Controller[Type, ID, Data, EntityID, EntityData]) Refresh(activityId ID) { func (slf *Controller[Type, ID, Data, EntityID, EntityData]) Refresh(activityId ID) {
slf.mutex.RLock()
activity, exist := slf.activities[activityId] activity, exist := slf.activities[activityId]
slf.mutex.RUnlock()
if !exist { if !exist {
return return
} }

View File

@ -32,11 +32,15 @@ func regController[Type, ID generic.Basic, Data any, EntityID generic.Basic, Ent
defer controllersLock.Unlock() defer controllersLock.Unlock()
controller.activities = make(map[ID]*Activity[Type, ID]) controller.activities = make(map[ID]*Activity[Type, ID])
controllerGlobalDataReader = append(controllerGlobalDataReader, func(handler func(activityType, activityId, data any)) { controllerGlobalDataReader = append(controllerGlobalDataReader, func(handler func(activityType, activityId, data any)) {
controller.mutex.RLock()
defer controller.mutex.RUnlock()
for activityId, data := range controller.globalData { for activityId, data := range controller.globalData {
handler(activityType, activityId, data) handler(activityType, activityId, data)
} }
}) })
controllerEntityDataReader = append(controllerEntityDataReader, func(handler func(activityType, activityId, entityId, data any)) { controllerEntityDataReader = append(controllerEntityDataReader, func(handler func(activityType, activityId, entityId, data any)) {
controller.mutex.RLock()
defer controller.mutex.RUnlock()
for activityId, entities := range controller.entityData { for activityId, entities := range controller.entityData {
for entityId, data := range entities { for entityId, data := range entities {
handler(activityType, activityId, entityId, data) handler(activityType, activityId, entityId, data)
@ -51,6 +55,8 @@ func regController[Type, ID generic.Basic, Data any, EntityID generic.Basic, Ent
tof = tof.Elem() tof = tof.Elem()
} }
controller.globalDataLoader = func(activityId any) { controller.globalDataLoader = func(activityId any) {
controller.mutex.Lock()
defer controller.mutex.Unlock()
var id = activityId.(ID) var id = activityId.(ID)
if _, exist := controller.globalData[id]; exist { if _, exist := controller.globalData[id]; exist {
return return
@ -71,6 +77,8 @@ func regController[Type, ID generic.Basic, Data any, EntityID generic.Basic, Ent
tof = tof.Elem() tof = tof.Elem()
} }
controller.entityDataLoader = func(activityId any, entityId any) { controller.entityDataLoader = func(activityId any, entityId any) {
controller.mutex.Lock()
defer controller.mutex.Unlock()
var id, eid = activityId.(ID), entityId.(EntityID) var id, eid = activityId.(ID), entityId.(EntityID)
entities, exist := controller.entityData[id] entities, exist := controller.entityData[id]
if !exist { if !exist {
@ -92,6 +100,7 @@ func regController[Type, ID generic.Basic, Data any, EntityID generic.Basic, Ent
controllers[activityType] = controller controllers[activityType] = controller
controllerRegisters[activityType] = func(activityType, activityId any) (act any, optionInitCallback func(activity any)) { controllerRegisters[activityType] = func(activityType, activityId any) (act any, optionInitCallback func(activity any)) {
var at, ai = activityType.(Type), activityId.(ID) var at, ai = activityType.(Type), activityId.(ID)
controller.mutex.Lock()
activity, exist := controller.activities[ai] activity, exist := controller.activities[ai]
if !exist { if !exist {
activity = &Activity[Type, ID]{ activity = &Activity[Type, ID]{
@ -107,6 +116,7 @@ func regController[Type, ID generic.Basic, Data any, EntityID generic.Basic, Ent
}, },
} }
} }
controller.mutex.Unlock()
controller.activities[activity.id] = activity controller.activities[activity.id] = activity
return activity, func(activity any) { return activity, func(activity any) {
act := activity.(*Activity[Type, ID]) act := activity.(*Activity[Type, ID])
@ -120,6 +130,8 @@ func regController[Type, ID generic.Basic, Data any, EntityID generic.Basic, Ent
} }
controllerReset[activityType] = func(activityId any) { controllerReset[activityType] = func(activityId any) {
var id = activityId.(ID) var id = activityId.(ID)
controller.mutex.Lock()
defer controller.mutex.Unlock()
delete(controller.globalData, id) delete(controller.globalData, id)
delete(controller.entityData, id) delete(controller.entityData, id)
} }