Skip to content

Commit

Permalink
refactor: 实现并发安全的ServiceAt(New) (#937)
Browse files Browse the repository at this point in the history
Co-authored-by: Pinenutn <[email protected]>
Co-authored-by: fy <[email protected]>
  • Loading branch information
3 people authored Aug 10, 2024
1 parent 41023b0 commit 6573fba
Show file tree
Hide file tree
Showing 26 changed files with 369 additions and 279 deletions.
11 changes: 7 additions & 4 deletions api/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import (

func groupList(c echo.Context) error {
var items []*dice.GroupInfo
for groupID, item := range myDice.ImSession.ServiceAtNew {
// Pinenutn: Range模板 ServiceAtNew重构代码
myDice.ImSession.ServiceAtNew.Range(func(groupID string, item *dice.GroupInfo) bool {
// Pinenutn: ServiceAtNew重构
item.GroupID = groupID
if !strings.HasPrefix(item.GroupID, "PG-") {
if item != nil {
Expand All @@ -31,7 +33,8 @@ func groupList(c echo.Context) error {
}
}
}
}
return true
})

return c.JSON(http.StatusOK, map[string]interface{}{
"items": items,
Expand All @@ -56,7 +59,7 @@ func groupSetOne(c echo.Context) error {
err := c.Bind(&v)

if err == nil {
_, exists := myDice.ImSession.ServiceAtNew[v.GroupID]
_, exists := myDice.ImSession.ServiceAtNew.Load(v.GroupID)
if exists {
for _, ep := range myDice.ImSession.EndPoints {
// if ep.UserId == v.DiceId {
Expand Down Expand Up @@ -95,7 +98,7 @@ func groupQuit(c echo.Context) error {
}

// 不太好弄,主要会出现多个帐号在群的情况
group, exists := myDice.ImSession.ServiceAtNew[v.GroupID]
group, exists := myDice.ImSession.ServiceAtNew.Load(v.GroupID)
if !exists {
return c.String(430, "")
}
Expand Down
12 changes: 8 additions & 4 deletions dice/builtin_commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,8 @@ func (d *Dice) registerCoreCommands() {
}

SetBotOnAtGroup(ctx, msg.GroupID)
ctx.Group = ctx.Session.ServiceAtNew[msg.GroupID]
// TODO:ServiceAtNew此处忽略是否合理?
ctx.Group, _ = ctx.Session.ServiceAtNew.Load(msg.GroupID)
ctx.IsCurGroupBotOn = true

text := DiceFormatTmpl(ctx, "核心:骰子开启")
Expand Down Expand Up @@ -595,7 +596,9 @@ func (d *Dice) registerCoreCommands() {

activeCount := 0
serveCount := 0
for _, gp := range d.ImSession.ServiceAtNew {
// Pinenutn: Range模板 ServiceAtNew重构代码
d.ImSession.ServiceAtNew.Range(func(_ string, gp *GroupInfo) bool {
// Pinenutn: ServiceAtNew重构
if gp.GroupID != "" &&
!strings.HasPrefix(gp.GroupID, "PG-") &&
gp.DiceIDExistsMap.Exists(ctx.EndPoint.UserID) {
Expand All @@ -604,7 +607,8 @@ func (d *Dice) registerCoreCommands() {
activeCount++
}
}
}
return true
})

onlineVer := ""
if d.Parent.AppVersionOnline != nil {
Expand Down Expand Up @@ -1093,7 +1097,7 @@ func (d *Dice) registerCoreCommands() {
n := strings.Split(gid, ":") // 不验证是否合法,反正下面会检查是否在 ServiceAtNew
platform := strings.Split(n[0], "-")[0]

gp, ok := ctx.Session.ServiceAtNew[gid]
gp, ok := ctx.Session.ServiceAtNew.Load(gid)
if !ok || len(n[0]) < 2 {
ReplyToSender(ctx, msg, fmt.Sprintf("群组列表中没有找到%s", gid))
return CmdExecuteResult{Matched: true, Solved: true}
Expand Down
73 changes: 42 additions & 31 deletions dice/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2154,8 +2154,9 @@ func (d *Dice) loads() {
}
}
d.DiceMasters = newDiceMasters
// 装载ServiceAt
d.ImSession.ServiceAtNew = map[string]*GroupInfo{}
// 装载ServiceAtNew
// Pinenutn: So,我还是不知道ServiceAtNew到底是个什么鬼东西……太反直觉了……
d.ImSession.ServiceAtNew = new(SyncMap[string, *GroupInfo])
_ = model.GroupInfoListGet(d.DBData, func(id string, updatedAt int64, data []byte) {
var groupInfo GroupInfo
err := json.Unmarshal(data, &groupInfo)
Expand All @@ -2176,7 +2177,7 @@ func (d *Dice) loads() {
groupInfo.DiceIDExistsMap.Delete(i)
}
}
d.ImSession.ServiceAtNew[id] = &groupInfo
d.ImSession.ServiceAtNew.Store(id, &groupInfo)
} else {
d.Logger.Errorf("加载群信息失败: %s", id)
}
Expand All @@ -2186,30 +2187,35 @@ func (d *Dice) loads() {
for _, i := range d.ExtList {
m[i.Name] = i
}

// 设置群扩展
for _, v := range d.ImSession.ServiceAtNew {
// Pinenutn: Range模板 ServiceAtNew重构代码
d.ImSession.ServiceAtNew.Range(func(_ string, groupInfo *GroupInfo) bool {
// Pinenutn: ServiceAtNew重构
var tmp []*ExtInfo
for _, i := range v.ActivatedExtList {
for _, i := range groupInfo.ActivatedExtList {
if m[i.Name] != nil {
tmp = append(tmp, m[i.Name])
}
}
v.ActivatedExtList = tmp
}
groupInfo.ActivatedExtList = tmp
return true
})

// 读取群变量
for _, g := range d.ImSession.ServiceAtNew {
if g.DiceIDActiveMap == nil {
g.DiceIDActiveMap = new(SyncMap[string, bool])
// Pinenutn: Range模板 ServiceAtNew重构代码
d.ImSession.ServiceAtNew.Range(func(key string, groupInfo *GroupInfo) bool {
// Pinenutn: ServiceAtNew重构
if groupInfo.DiceIDActiveMap == nil {
groupInfo.DiceIDActiveMap = new(SyncMap[string, bool])
}
if g.DiceIDExistsMap == nil {
g.DiceIDExistsMap = new(SyncMap[string, bool])
if groupInfo.DiceIDExistsMap == nil {
groupInfo.DiceIDExistsMap = new(SyncMap[string, bool])
}
if g.BotList == nil {
g.BotList = new(SyncMap[string, bool])
if groupInfo.BotList == nil {
groupInfo.BotList = new(SyncMap[string, bool])
}
}
return true
})

if d.VersionCode != 0 && d.VersionCode < 10000 {
d.CustomReplyConfigEnable = false
Expand Down Expand Up @@ -2331,10 +2337,13 @@ func (d *Dice) loads() {
// 设置全局群名缓存和用户名缓存
dm := d.Parent
now := time.Now().Unix()
for k, v := range d.ImSession.ServiceAtNew {
dm.GroupNameCache.Store(k, &GroupNameCacheItem{Name: v.GroupName, time: now})
}

// Pinenutn: Range模板 ServiceAtNew重构代码
d.ImSession.ServiceAtNew.Range(func(key string, groupInfo *GroupInfo) bool {
// Pinenutn: ServiceAtNew重构
// Pinenutn: 这里曾经可能是个Lockfree.hashmap? 函数有变动
dm.GroupNameCache.Store(key, &GroupNameCacheItem{Name: groupInfo.GroupName, time: now})
return true
})
d.Logger.Info("serve.yaml loaded")
} else {
// 这里是没有加载到配置文件,所以写默认设置项
Expand Down Expand Up @@ -2532,30 +2541,32 @@ func (d *Dice) Save(isAuto bool) {
}
}
}

for _, g := range d.ImSession.ServiceAtNew {
// Pinenutn: Range模板 ServiceAtNew重构代码
d.ImSession.ServiceAtNew.Range(func(key string, groupInfo *GroupInfo) bool {
// Pinenutn: ServiceAtNew重构
// 保存群内玩家信息
if g.Players != nil {
g.Players.Range(func(key string, value *GroupPlayerInfo) bool {
if groupInfo.Players != nil {
groupInfo.Players.Range(func(key string, value *GroupPlayerInfo) bool {
if value.UpdatedAtTime != 0 {
_ = model.GroupPlayerInfoSave(d.DBData, g.GroupID, key, (*model.GroupPlayerInfoBase)(value))
_ = model.GroupPlayerInfoSave(d.DBData, groupInfo.GroupID, key, (*model.GroupPlayerInfoBase)(value))
value.UpdatedAtTime = 0
}
return true
})
}

if g.UpdatedAtTime != 0 {
data, err := json.Marshal(g)
if groupInfo.UpdatedAtTime != 0 {
data, err := json.Marshal(groupInfo)
if err == nil {
err := model.GroupInfoSave(d.DBData, g.GroupID, g.UpdatedAtTime, data)
err := model.GroupInfoSave(d.DBData, groupInfo.GroupID, groupInfo.UpdatedAtTime, data)
if err != nil {
d.Logger.Warnf("保存群组数据失败 %v : %v", g.GroupID, err.Error())
d.Logger.Warnf("保存群组数据失败 %v : %v", groupInfo.GroupID, err.Error())
}
g.UpdatedAtTime = 0
groupInfo.UpdatedAtTime = 0
}
}
}
return true
})

// 同步全部属性数据:个人角色卡、群内角色卡、群数据、个人全局数据
d.AttrsManager.CheckForSave()
Expand Down
29 changes: 17 additions & 12 deletions dice/dice.go
Original file line number Diff line number Diff line change
Expand Up @@ -366,9 +366,10 @@ func (d *Dice) Init() {
initVerify()

d.CommandCompatibleMode = true
// Pinenutn: 预先初始化对应的SyncMap
d.ImSession = &IMSession{}
d.ImSession.Parent = d
d.ImSession.ServiceAtNew = make(map[string]*GroupInfo)
d.ImSession.ServiceAtNew = new(SyncMap[string, *GroupInfo])
d.CmdMap = CmdMapCls{}
d.GameSystemMap = new(SyncMap[string, *GameSystemTemplate])
d.ConfigManager = NewConfigManager(filepath.Join(d.BaseConfig.DataDir, "configs", "plugin-configs.json"))
Expand Down Expand Up @@ -449,23 +450,24 @@ func (d *Dice) Init() {
// 自动更新群信息
for _, i := range d.ImSession.EndPoints {
if i.Enable {
for k, v := range d.ImSession.ServiceAtNew {
// Pinenutn: Range模板 ServiceAtNew重构代码
d.ImSession.ServiceAtNew.Range(func(key string, groupInfo *GroupInfo) bool {
// Pinenutn: ServiceAtNew重构
// TODO: 注意这里的Active可能不需要改
if !strings.HasPrefix(k, "PG-") && v.Active {
if !strings.HasPrefix(key, "PG-") && groupInfo.Active {
diceID := i.UserID
now := time.Now().Unix()

// 上次被人使用小于60s
if now-v.RecentDiceSendTime < 60 {
if now-groupInfo.RecentDiceSendTime < 60 {
// 在群内存在,且开启时
if _, exists := v.DiceIDExistsMap.Load(diceID); exists {
if _, exists := v.DiceIDActiveMap.Load(diceID); exists {
i.Adapter.GetGroupInfoAsync(k)
}
if groupInfo.DiceIDExistsMap.Exists(diceID) && groupInfo.DiceIDActiveMap.Exists(diceID) {
i.Adapter.GetGroupInfoAsync(key)
}
}
}
}
return true
})
}
}
}
Expand Down Expand Up @@ -637,9 +639,12 @@ func (d *Dice) ExtAliasToName(s string) string {
}

func (d *Dice) ExtRemove(ei *ExtInfo) bool {
for _, i := range d.ImSession.ServiceAtNew {
i.ExtInactive(ei)
}
// Pinenutn: Range模板 ServiceAtNew重构代码
d.ImSession.ServiceAtNew.Range(func(key string, groupInfo *GroupInfo) bool {
// Pinenutn: ServiceAtNew重构
groupInfo.ExtInactive(ei)
return true
})

for index, i := range d.ExtList {
if i == ei {
Expand Down
24 changes: 12 additions & 12 deletions dice/dice_ban.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,15 +205,15 @@ func (i *BanListInfo) addJointScore(_ string, score int64, place string, reason
i.AddScoreBase(place, int64(score), place, reason, ctx)
}
if i.JointScorePercentOfInviter > 0 {
group := d.ImSession.ServiceAtNew[place]
if group != nil && group.InviteUserID != "" {
rank := i.NoticeCheckPrepare(group.InviteUserID)
groupInfo, ok := d.ImSession.ServiceAtNew.Load(place)
if ok && groupInfo.InviteUserID != "" {
rank := i.NoticeCheckPrepare(groupInfo.InviteUserID)
score := i.JointScorePercentOfInviter * float64(score)
i.AddScoreBase(group.InviteUserID, int64(score), place, reason, ctx)
i.AddScoreBase(groupInfo.InviteUserID, int64(score), place, reason, ctx)

// text := fmt.Sprintf("提醒: 你邀请的骰子在群组<%s>中被禁言/踢出/指令刷屏了", group.GroupName)
// ReplyPersonRaw(ctx, &Message{Sender: SenderBase{UserId: group.InviteUserId}}, text, "")
return group.InviteUserID, rank
// text := fmt.Sprintf("提醒: 你邀请的骰子在群组<%s>中被禁言/踢出/指令刷屏了", groupInfo.GroupName)
// ReplyPersonRaw(ctx, &Message{Sender: SenderBase{UserId: groupInfo.InviteUserId}}, text, "")
return groupInfo.InviteUserID, rank
}
}
return "", BanRankNormal
Expand Down Expand Up @@ -267,12 +267,12 @@ func (i *BanListInfo) NoticeCheck(uid string, place string, oldRank BanRankType,

// 发给邀请者
time.Sleep(1 * time.Second)
group := i.Parent.ImSession.ServiceAtNew[place]
if group != nil && group.InviteUserID != "" {
VarSetValueStr(ctx, "$t事发群名", group.GroupName)
VarSetValueStr(ctx, "$t事发群号", group.GroupID)
groupInfo, ok := i.Parent.ImSession.ServiceAtNew.Load(place)
if ok && groupInfo.InviteUserID != "" {
VarSetValueStr(ctx, "$t事发群名", groupInfo.GroupName)
VarSetValueStr(ctx, "$t事发群号", groupInfo.GroupID)
text := DiceFormatTmpl(ctx, "核心:黑名单触发_邀请人")
ReplyPersonRaw(ctx, &Message{Sender: SenderBase{UserID: group.InviteUserID}}, text, "")
ReplyPersonRaw(ctx, &Message{Sender: SenderBase{UserID: groupInfo.InviteUserID}}, text, "")
}
}

Expand Down
11 changes: 7 additions & 4 deletions dice/dice_censor.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,10 @@ func (d *Dice) CensorMsg(mctx *MsgContext, msg *Message, checkContent string, se
}

mctx.Censored = true
group := mctx.Session.ServiceAtNew[msg.GroupID]
groupInfo, ok := mctx.Session.ServiceAtNew.Load(msg.GroupID)
if !ok {
d.Logger.Warn("Dice CenSor获取GroupInfo失败")
}
thresholds := d.CensorThresholds

// 保证按程度依次降低来处理
Expand Down Expand Up @@ -164,7 +167,7 @@ func (d *Dice) CensorMsg(mctx *MsgContext, msg *Message, checkContent string, se
if msg.MessageType == "group" {
text = fmt.Sprintf(
"群(%s)内<%s>(%s)触发<%s>敏感词拦截",
group.GroupID,
groupInfo.GroupID,
msg.Sender.Nickname,
msg.Sender.UserID,
levelText,
Expand Down Expand Up @@ -205,7 +208,7 @@ func (d *Dice) CensorMsg(mctx *MsgContext, msg *Message, checkContent string, se
// 拉黑邀请人
if msg.MessageType == "group" {
d.BanList.AddScoreBase(
group.InviteUserID,
groupInfo.InviteUserID,
d.BanList.ThresholdBan,
"敏感词审查",
"触发<"+levelText+">敏感词",
Expand All @@ -223,7 +226,7 @@ func (d *Dice) CensorMsg(mctx *MsgContext, msg *Message, checkContent string, se
d.BanList.AddScoreByCensor(
msg.Sender.UserID,
int64(score),
group.GroupID,
groupInfo.GroupID,
levelText,
mctx,
)
Expand Down
12 changes: 8 additions & 4 deletions dice/dice_jsvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,9 +199,12 @@ func (d *Dice) JsInit() {
ei.OnLoad()
}
d.ApplyExtDefaultSettings()
for _, i := range d.ImSession.ServiceAtNew {
i.ExtActive(ei)
}
// Pinenutn: Range模板 ServiceAtNew重构代码
d.ImSession.ServiceAtNew.Range(func(key string, groupInfo *GroupInfo) bool {
// Pinenutn: ServiceAtNew重构
groupInfo.ExtActive(ei)
return true
})
})
_ = ext.Set("registerStringConfig", func(ei *ExtInfo, key string, defaultValue string, description string) error {
if ei.dice == nil {
Expand Down Expand Up @@ -621,7 +624,8 @@ func (d *Dice) jsClear() {
// 清理脚本列表
d.JsScriptList = []*JsScriptInfo{}
// 清理规则模板
d.GameSystemMap = &SyncMap[string, *GameSystemTemplate]{}
// Pinenutn: 由于切换成了其他的syncMap,所以初始化策略需要修改
d.GameSystemMap = new(SyncMap[string, *GameSystemTemplate])
d.RegisterBuiltinSystemTemplate()
// 关闭js vm
if d.JsLoop != nil {
Expand Down
Loading

0 comments on commit 6573fba

Please sign in to comment.