mirror of
https://github.com/FlourishingWorld/hk4e.git
synced 2026-03-01 00:35:36 +08:00
修改聊天数据存储结构
This commit is contained in:
@@ -10,13 +10,6 @@ import (
|
|||||||
"go.mongodb.org/mongo-driver/mongo"
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PlayerDb 只从数据库读写的结构
|
|
||||||
type PlayerDb struct {
|
|
||||||
ID primitive.ObjectID `bson:"_id,omitempty"`
|
|
||||||
PlayerID uint32 `bson:"PlayerID"` // 玩家uid
|
|
||||||
ChatMsgMap map[uint32][]*model.ChatMsg // 聊天信息
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Dao) InsertPlayer(player *model.Player) error {
|
func (d *Dao) InsertPlayer(player *model.Player) error {
|
||||||
db := d.db.Collection("player")
|
db := d.db.Collection("player")
|
||||||
_, err := db.InsertOne(context.TODO(), player)
|
_, err := db.InsertOne(context.TODO(), player)
|
||||||
@@ -26,9 +19,9 @@ func (d *Dao) InsertPlayer(player *model.Player) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Dao) InsertPlayerDb(playerDb *PlayerDb) error {
|
func (d *Dao) InsertChatMsg(chatMsg *model.ChatMsg) error {
|
||||||
db := d.db.Collection("player_db")
|
db := d.db.Collection("chat_msg")
|
||||||
_, err := db.InsertOne(context.TODO(), playerDb)
|
_, err := db.InsertOne(context.TODO(), chatMsg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -52,14 +45,14 @@ func (d *Dao) InsertPlayerList(playerList []*model.Player) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Dao) InsertPlayerDbList(playerDbList []*PlayerDb) error {
|
func (d *Dao) InsertChatMsgList(chatMsgList []*model.ChatMsg) error {
|
||||||
if len(playerDbList) == 0 {
|
if len(chatMsgList) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
db := d.db.Collection("player_db")
|
db := d.db.Collection("chat_msg")
|
||||||
modelOperateList := make([]mongo.WriteModel, 0)
|
modelOperateList := make([]mongo.WriteModel, 0)
|
||||||
for _, playerDb := range playerDbList {
|
for _, chatMsg := range chatMsgList {
|
||||||
modelOperate := mongo.NewInsertOneModel().SetDocument(playerDb)
|
modelOperate := mongo.NewInsertOneModel().SetDocument(chatMsg)
|
||||||
modelOperateList = append(modelOperateList, modelOperate)
|
modelOperateList = append(modelOperateList, modelOperate)
|
||||||
}
|
}
|
||||||
_, err := db.BulkWrite(context.TODO(), modelOperateList)
|
_, err := db.BulkWrite(context.TODO(), modelOperateList)
|
||||||
@@ -78,9 +71,9 @@ func (d *Dao) DeletePlayer(playerID uint32) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Dao) DeletePlayerDb(playerID uint32) error {
|
func (d *Dao) DeleteChatMsg(id primitive.ObjectID) error {
|
||||||
db := d.db.Collection("player_db")
|
db := d.db.Collection("chat_msg")
|
||||||
_, err := db.DeleteOne(context.TODO(), bson.D{{"PlayerID", playerID}})
|
_, err := db.DeleteOne(context.TODO(), bson.D{{"_id", id}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -104,14 +97,14 @@ func (d *Dao) DeletePlayerList(playerIDList []uint32) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Dao) DeletePlayerDbList(playerIDList []uint32) error {
|
func (d *Dao) DeleteChatMsgList(idList []primitive.ObjectID) error {
|
||||||
if len(playerIDList) == 0 {
|
if len(idList) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
db := d.db.Collection("player_db")
|
db := d.db.Collection("chat_msg")
|
||||||
modelOperateList := make([]mongo.WriteModel, 0)
|
modelOperateList := make([]mongo.WriteModel, 0)
|
||||||
for _, playerID := range playerIDList {
|
for _, id := range idList {
|
||||||
modelOperate := mongo.NewDeleteOneModel().SetFilter(bson.D{{"PlayerID", playerID}})
|
modelOperate := mongo.NewDeleteOneModel().SetFilter(bson.D{{"_id", id}})
|
||||||
modelOperateList = append(modelOperateList, modelOperate)
|
modelOperateList = append(modelOperateList, modelOperate)
|
||||||
}
|
}
|
||||||
_, err := db.BulkWrite(context.TODO(), modelOperateList)
|
_, err := db.BulkWrite(context.TODO(), modelOperateList)
|
||||||
@@ -134,12 +127,12 @@ func (d *Dao) UpdatePlayer(player *model.Player) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Dao) UpdatePlayerDb(playerDb *PlayerDb) error {
|
func (d *Dao) UpdateChatMsg(chatMsg *model.ChatMsg) error {
|
||||||
db := d.db.Collection("player_db")
|
db := d.db.Collection("chat_msg")
|
||||||
_, err := db.UpdateOne(
|
_, err := db.UpdateOne(
|
||||||
context.TODO(),
|
context.TODO(),
|
||||||
bson.D{{"PlayerID", playerDb.PlayerID}},
|
bson.D{{"_id", chatMsg.ID}},
|
||||||
bson.D{{"$set", playerDb}},
|
bson.D{{"$set", chatMsg}},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -164,14 +157,14 @@ func (d *Dao) UpdatePlayerList(playerList []*model.Player) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Dao) UpdatePlayerDbList(playerDbList []*PlayerDb) error {
|
func (d *Dao) UpdateChatMsgList(chatMsgList []*model.ChatMsg) error {
|
||||||
if len(playerDbList) == 0 {
|
if len(chatMsgList) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
db := d.db.Collection("player_db")
|
db := d.db.Collection("chat_msg")
|
||||||
modelOperateList := make([]mongo.WriteModel, 0)
|
modelOperateList := make([]mongo.WriteModel, 0)
|
||||||
for _, playerDb := range playerDbList {
|
for _, chatMsg := range chatMsgList {
|
||||||
modelOperate := mongo.NewUpdateOneModel().SetFilter(bson.D{{"PlayerID", playerDb.PlayerID}}).SetUpdate(bson.D{{"$set", playerDb}})
|
modelOperate := mongo.NewUpdateOneModel().SetFilter(bson.D{{"_id", chatMsg.ID}}).SetUpdate(bson.D{{"$set", chatMsg}})
|
||||||
modelOperateList = append(modelOperateList, modelOperate)
|
modelOperateList = append(modelOperateList, modelOperate)
|
||||||
}
|
}
|
||||||
_, err := db.BulkWrite(context.TODO(), modelOperateList)
|
_, err := db.BulkWrite(context.TODO(), modelOperateList)
|
||||||
@@ -195,24 +188,20 @@ func (d *Dao) QueryPlayerByID(playerID uint32) (*model.Player, error) {
|
|||||||
return player, nil
|
return player, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Dao) QueryPlayerDbByID(playerID uint32) (*PlayerDb, error) {
|
func (d *Dao) QueryChatMsgByID(id primitive.ObjectID) (*model.ChatMsg, error) {
|
||||||
db := d.db.Collection("player_db")
|
db := d.db.Collection("chat_msg")
|
||||||
result := db.FindOne(
|
result := db.FindOne(
|
||||||
context.TODO(),
|
context.TODO(),
|
||||||
bson.D{{"PlayerID", playerID}},
|
bson.D{{"_id", id}},
|
||||||
)
|
)
|
||||||
playerDb := new(PlayerDb)
|
chatMsg := new(model.ChatMsg)
|
||||||
err := result.Decode(playerDb)
|
err := result.Decode(chatMsg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if playerDb.ChatMsgMap == nil {
|
return chatMsg, nil
|
||||||
playerDb.ChatMsgMap = make(map[uint32][]*model.ChatMsg)
|
|
||||||
}
|
|
||||||
return playerDb, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryPlayerList 危险接口 非测试禁止使用
|
|
||||||
func (d *Dao) QueryPlayerList() ([]*model.Player, error) {
|
func (d *Dao) QueryPlayerList() ([]*model.Player, error) {
|
||||||
db := d.db.Collection("player")
|
db := d.db.Collection("player")
|
||||||
find, err := db.Find(
|
find, err := db.Find(
|
||||||
@@ -233,3 +222,45 @@ func (d *Dao) QueryPlayerList() ([]*model.Player, error) {
|
|||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *Dao) QueryChatMsgList() ([]*model.ChatMsg, error) {
|
||||||
|
db := d.db.Collection("chat_msg")
|
||||||
|
find, err := db.Find(
|
||||||
|
context.TODO(),
|
||||||
|
bson.D{},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := make([]*model.ChatMsg, 0)
|
||||||
|
for find.Next(context.TODO()) {
|
||||||
|
item := new(model.ChatMsg)
|
||||||
|
err = find.Decode(item)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, item)
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Dao) QueryChatMsgListByUid(uid uint32) ([]*model.ChatMsg, error) {
|
||||||
|
db := d.db.Collection("chat_msg")
|
||||||
|
find, err := db.Find(
|
||||||
|
context.TODO(),
|
||||||
|
bson.D{{"ToUid", uid}, {"Uid", uid}},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := make([]*model.ChatMsg, 0)
|
||||||
|
for find.Next(context.TODO()) {
|
||||||
|
item := new(model.ChatMsg)
|
||||||
|
err = find.Decode(item)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, item)
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -105,6 +105,10 @@ func (g *GameManager) SendPrivateChat(player *model.Player, targetUid uint32, co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
chatMsg := g.ConvChatInfoToChatMsg(chatInfo)
|
chatMsg := g.ConvChatInfoToChatMsg(chatInfo)
|
||||||
|
|
||||||
|
// 写入db
|
||||||
|
go USER_MANAGER.SaveUserChatMsgToDbSync(chatMsg)
|
||||||
|
|
||||||
// 消息加入自己的队列
|
// 消息加入自己的队列
|
||||||
msgList, exist := player.ChatMsgMap[targetUid]
|
msgList, exist := player.ChatMsgMap[targetUid]
|
||||||
if !exist {
|
if !exist {
|
||||||
@@ -141,15 +145,10 @@ func (g *GameManager) SendPrivateChat(player *model.Player, targetUid uint32, co
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
} else {
|
|
||||||
// 目标玩家全服离线
|
|
||||||
chatMsgMap := map[uint32][]*model.ChatMsg{
|
|
||||||
player.PlayerID: {chatMsg},
|
|
||||||
}
|
|
||||||
go USER_MANAGER.AppendOfflineUserChatMsgToDbSync(targetUid, chatMsgMap)
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 消息加入目标玩家的队列
|
// 消息加入目标玩家的队列
|
||||||
msgList, exist = targetPlayer.ChatMsgMap[player.PlayerID]
|
msgList, exist = targetPlayer.ChatMsgMap[player.PlayerID]
|
||||||
if !exist {
|
if !exist {
|
||||||
@@ -327,6 +326,9 @@ func (g *GameManager) ServerChatMsgNotify(chatMsgInfo *mq.ChatMsgInfo) {
|
|||||||
if !exist {
|
if !exist {
|
||||||
msgList = make([]*model.ChatMsg, 0)
|
msgList = make([]*model.ChatMsg, 0)
|
||||||
}
|
}
|
||||||
|
if len(msgList) > MaxMsgListLen {
|
||||||
|
msgList = msgList[1:]
|
||||||
|
}
|
||||||
msgList = append(msgList, chatMsg)
|
msgList = append(msgList, chatMsg)
|
||||||
targetPlayer.ChatMsgMap[chatMsgInfo.Uid] = msgList
|
targetPlayer.ChatMsgMap[chatMsgInfo.Uid] = msgList
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"hk4e/gs/dao"
|
"hk4e/gs/dao"
|
||||||
"hk4e/gs/model"
|
"hk4e/gs/model"
|
||||||
"hk4e/pkg/logger"
|
"hk4e/pkg/logger"
|
||||||
"hk4e/pkg/object"
|
|
||||||
"hk4e/protocol/proto"
|
"hk4e/protocol/proto"
|
||||||
|
|
||||||
"github.com/vmihailenco/msgpack/v5"
|
"github.com/vmihailenco/msgpack/v5"
|
||||||
@@ -142,8 +141,7 @@ func (u *UserManager) OnlineUser(userId uint32, clientSeq uint32, gateAppId stri
|
|||||||
if player != nil {
|
if player != nil {
|
||||||
u.SaveUserToRedisSync(player)
|
u.SaveUserToRedisSync(player)
|
||||||
u.ChangeUserDbState(player, model.DbNormal)
|
u.ChangeUserDbState(player, model.DbNormal)
|
||||||
playerDb := u.LoadUserChatMsgFromDbSync(userId)
|
player.ChatMsgMap = u.LoadUserChatMsgFromDbSync(userId)
|
||||||
player.ChatMsgMap = playerDb.ChatMsgMap
|
|
||||||
} else {
|
} else {
|
||||||
logger.Error("can not find user from db, uid: %v", userId)
|
logger.Error("can not find user from db, uid: %v", userId)
|
||||||
}
|
}
|
||||||
@@ -179,14 +177,9 @@ func (u *UserManager) OfflineUser(player *model.Player, changeGsInfo *ChangeGsIn
|
|||||||
logger.Error("marshal player data error: %v", err)
|
logger.Error("marshal player data error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
chatMsgMapData, err := object.DeepMarshal(&player.ChatMsgMap)
|
|
||||||
if err != nil {
|
|
||||||
logger.Error("marshal chat msg map error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
endTime := time.Now().UnixNano()
|
endTime := time.Now().UnixNano()
|
||||||
costTime := endTime - startTime
|
costTime := endTime - startTime
|
||||||
logger.Info("offline copy player data and chat msg cost time: %v ns", costTime)
|
logger.Info("offline copy player data cost time: %v ns", costTime)
|
||||||
go func() {
|
go func() {
|
||||||
playerCopy := new(model.Player)
|
playerCopy := new(model.Player)
|
||||||
err := msgpack.Unmarshal(playerData, playerCopy)
|
err := msgpack.Unmarshal(playerData, playerCopy)
|
||||||
@@ -197,16 +190,6 @@ func (u *UserManager) OfflineUser(player *model.Player, changeGsInfo *ChangeGsIn
|
|||||||
playerCopy.DbState = player.DbState
|
playerCopy.DbState = player.DbState
|
||||||
u.SaveUserToDbSync(playerCopy)
|
u.SaveUserToDbSync(playerCopy)
|
||||||
u.SaveUserToRedisSync(playerCopy)
|
u.SaveUserToRedisSync(playerCopy)
|
||||||
chatMsgMap := make(map[uint32][]*model.ChatMsg)
|
|
||||||
err = object.DeepUnmarshal(&chatMsgMap, chatMsgMapData)
|
|
||||||
if err != nil {
|
|
||||||
logger.Error("unmarshal chat msg map error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
playerDb := new(dao.PlayerDb)
|
|
||||||
playerDb.PlayerID = playerCopy.PlayerID
|
|
||||||
playerDb.ChatMsgMap = chatMsgMap
|
|
||||||
u.SaveUserChatMsgToDbSync(playerDb)
|
|
||||||
LOCAL_EVENT_MANAGER.localEventChan <- &LocalEvent{
|
LOCAL_EVENT_MANAGER.localEventChan <- &LocalEvent{
|
||||||
EventId: UserOfflineSaveToDbFinish,
|
EventId: UserOfflineSaveToDbFinish,
|
||||||
Msg: &PlayerOfflineInfo{
|
Msg: &PlayerOfflineInfo{
|
||||||
@@ -479,49 +462,33 @@ func (u *UserManager) SaveUserListToDbSync(insertPlayerList []*model.Player, upd
|
|||||||
logger.Info("save user finish, insert user count: %v, update user count: %v", len(insertPlayerList), len(updatePlayerList))
|
logger.Info("save user finish, insert user count: %v, update user count: %v", len(insertPlayerList), len(updatePlayerList))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserManager) LoadUserChatMsgFromDbSync(userId uint32) *dao.PlayerDb {
|
func (u *UserManager) LoadUserChatMsgFromDbSync(userId uint32) map[uint32][]*model.ChatMsg {
|
||||||
playerDb, err := u.dao.QueryPlayerDbByID(userId)
|
chatMsgMap := make(map[uint32][]*model.ChatMsg)
|
||||||
|
chatMsgList, err := u.dao.QueryChatMsgListByUid(userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("query player db error: %v", err)
|
logger.Error("query chat msg list error: %v", err)
|
||||||
return nil
|
return chatMsgMap
|
||||||
}
|
}
|
||||||
return playerDb
|
for _, chatMsg := range chatMsgList {
|
||||||
|
msgList, exist := chatMsgMap[chatMsg.ToUid]
|
||||||
|
if !exist {
|
||||||
|
msgList = make([]*model.ChatMsg, 0)
|
||||||
|
}
|
||||||
|
if len(msgList) > MaxMsgListLen {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
msgList = append(msgList, chatMsg)
|
||||||
|
chatMsgMap[chatMsg.ToUid] = msgList
|
||||||
|
}
|
||||||
|
return chatMsgMap
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserManager) SaveUserChatMsgToDbSync(playerDb *dao.PlayerDb) {
|
func (u *UserManager) SaveUserChatMsgToDbSync(chatMsg *model.ChatMsg) {
|
||||||
_, err := u.dao.QueryPlayerDbByID(playerDb.PlayerID)
|
err := u.dao.InsertChatMsg(chatMsg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := u.dao.InsertPlayerDb(playerDb)
|
logger.Error("insert chat msg error: %v", err)
|
||||||
if err != nil {
|
|
||||||
logger.Error("insert player db error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err := u.dao.UpdatePlayerDb(playerDb)
|
|
||||||
if err != nil {
|
|
||||||
logger.Error("update player db error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UserManager) AppendOfflineUserChatMsgToDbSync(userId uint32, chatMsgMap map[uint32][]*model.ChatMsg) {
|
|
||||||
playerDb := u.LoadUserChatMsgFromDbSync(userId)
|
|
||||||
if playerDb == nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for uid, msgList := range chatMsgMap {
|
|
||||||
allMsgList, exist := playerDb.ChatMsgMap[uid]
|
|
||||||
if !exist {
|
|
||||||
allMsgList = make([]*model.ChatMsg, 0)
|
|
||||||
}
|
|
||||||
allMsgList = append(allMsgList, msgList...)
|
|
||||||
if len(allMsgList) > MaxMsgListLen {
|
|
||||||
allMsgList = allMsgList[len(allMsgList)-MaxMsgListLen:]
|
|
||||||
}
|
|
||||||
playerDb.ChatMsgMap[uid] = allMsgList
|
|
||||||
}
|
|
||||||
u.SaveUserChatMsgToDbSync(playerDb)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserManager) LoadUserFromRedisSync(userId uint32) *model.Player {
|
func (u *UserManager) LoadUserFromRedisSync(userId uint32) *model.Player {
|
||||||
|
|||||||
@@ -1,16 +1,21 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ChatMsgTypeText = iota
|
ChatMsgTypeText = iota
|
||||||
ChatMsgTypeIcon
|
ChatMsgTypeIcon
|
||||||
)
|
)
|
||||||
|
|
||||||
type ChatMsg struct {
|
type ChatMsg struct {
|
||||||
Time uint32
|
ID primitive.ObjectID `bson:"_id,omitempty"`
|
||||||
ToUid uint32
|
Time uint32 `bson:"Time"`
|
||||||
Uid uint32
|
ToUid uint32 `bson:"ToUid"`
|
||||||
IsRead bool
|
Uid uint32 `bson:"Uid"`
|
||||||
MsgType uint8
|
IsRead bool `bson:"IsRead"`
|
||||||
Text string
|
MsgType uint8 `bson:"MsgType"`
|
||||||
Icon uint32
|
Text string `bson:"Text"`
|
||||||
|
Icon uint32 `bson:"Icon"`
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user