diff --git a/internal/rpc/group/g.go b/internal/rpc/group/g.go index db056ef63..3bbbb4afa 100644 --- a/internal/rpc/group/g.go +++ b/internal/rpc/group/g.go @@ -10,6 +10,7 @@ import ( "errors" "math/big" "strconv" + "strings" "time" ) @@ -45,6 +46,24 @@ func GetPublicUserInfoMap(ctx context.Context, userIDs []string) (map[string]*sd }), nil } +func GetUsername(ctx context.Context, userIDs []string) (map[string]string, error) { + if len(userIDs) == 0 { + return map[string]string{}, nil + } + users, err := GetPublicUserInfo(ctx, userIDs) + if err != nil { + return nil, err + } + if ids := utils.Single(userIDs, utils.Slice(users, func(e *sdkws.PublicUserInfo) string { + return e.UserID + })); len(ids) > 0 { + return nil, constant.ErrUserIDNotFound.Wrap(strings.Join(ids, ",")) + } + return utils.SliceToMapAny(users, func(e *sdkws.PublicUserInfo) (string, string) { + return e.UserID, e.Nickname + }), nil +} + func GroupNotification(ctx context.Context, groupID string) { var conversationReq pbConversation.ModifyConversationFieldReq conversation := pbConversation.Conversation{ diff --git a/internal/rpc/group/group.go b/internal/rpc/group/group.go index 08a32bc35..9bdb77165 100644 --- a/internal/rpc/group/group.go +++ b/internal/rpc/group/group.go @@ -159,6 +159,7 @@ func (s *groupServer) CreateGroup(ctx context.Context, req *pbGroup.CreateGroupR group.GroupID = genGroupID(ctx, req.GroupInfo.GroupID) joinGroup := func(userID string, roleLevel int32) error { groupMember := PbToDbGroupMember(userMap[userID]) + groupMember.Nickname = "" groupMember.GroupID = group.GroupID groupMember.RoleLevel = roleLevel groupMember.OperatorUserID = tracelog.GetOpUserID(ctx) @@ -240,7 +241,7 @@ func (s *groupServer) GetJoinedGroupList(ctx context.Context, req *pbGroup.GetJo resp.Groups = utils.Slice(utils.Order(groupIDs, groups, func(group *relationTb.GroupModel) string { return group.GroupID }), func(group *relationTb.GroupModel) *open_im_sdk.GroupInfo { - return DbToPbGroupInfo(group, ownerMap[group.GroupID].UserID, uint32(groupMemberNum[group.GroupID])) + return DbToPbGroupInfo(group, ownerMap[group.GroupID].UserID, groupMemberNum[group.GroupID]) }) return resp, nil } @@ -321,6 +322,7 @@ func (s *groupServer) InviteUserToGroup(ctx context.Context, req *pbGroup.Invite var groupMembers []*relationTb.GroupMemberModel for _, userID := range req.InvitedUserIDs { member := PbToDbGroupMember(userMap[userID]) + member.Nickname = "" member.GroupID = req.GroupID member.RoleLevel = constant.GroupOrdinaryUsers member.OperatorUserID = opUserID @@ -352,7 +354,16 @@ func (s *groupServer) GetGroupAllMember(ctx context.Context, req *pbGroup.GetGro if err != nil { return nil, err } + nameMap, err := GetUsername(ctx, utils.Filter(members, func(e *relationTb.GroupMemberModel) (string, bool) { + return e.UserID, e.Nickname == "" + })) + if err != nil { + return nil, err + } resp.Members = utils.Slice(members, func(e *relationTb.GroupMemberModel) *open_im_sdk.GroupMemberFullInfo { + if e.Nickname == "" { + e.Nickname = nameMap[e.UserID] + } return DbToPbGroupMembersCMSResp(e) }) return resp, nil @@ -365,7 +376,16 @@ func (s *groupServer) GetGroupMemberList(ctx context.Context, req *pbGroup.GetGr return nil, err } resp.Total = total + nameMap, err := GetUsername(ctx, utils.Filter(members, func(e *relationTb.GroupMemberModel) (string, bool) { + return e.UserID, e.Nickname == "" + })) + if err != nil { + return nil, err + } resp.Members = utils.Slice(members, func(e *relationTb.GroupMemberModel) *open_im_sdk.GroupMemberFullInfo { + if e.Nickname == "" { + e.Nickname = nameMap[e.UserID] + } return DbToPbGroupMembersCMSResp(e) }) return resp, nil @@ -450,7 +470,16 @@ func (s *groupServer) GetGroupMembersInfo(ctx context.Context, req *pbGroup.GetG if err != nil { return nil, err } + nameMap, err := GetUsername(ctx, utils.Filter(members, func(e *relationTb.GroupMemberModel) (string, bool) { + return e.UserID, e.Nickname == "" + })) + if err != nil { + return nil, err + } resp.Members = utils.Slice(members, func(e *relationTb.GroupMemberModel) *open_im_sdk.GroupMemberFullInfo { + if e.Nickname == "" { + e.Nickname = nameMap[e.UserID] + } return DbToPbGroupMembersCMSResp(e) }) return resp, nil @@ -801,7 +830,16 @@ func (s *groupServer) GetGroupMembersCMS(ctx context.Context, req *pbGroup.GetGr return nil, err } resp.Total = total + nameMap, err := GetUsername(ctx, utils.Filter(members, func(e *relationTb.GroupMemberModel) (string, bool) { + return e.UserID, e.Nickname == "" + })) + if err != nil { + return nil, err + } resp.Members = utils.Slice(members, func(e *relationTb.GroupMemberModel) *open_im_sdk.GroupMemberFullInfo { + if e.Nickname == "" { + e.Nickname = nameMap[e.UserID] + } return DbToPbGroupMembersCMSResp(e) }) return resp, nil @@ -1011,8 +1049,8 @@ func (s *groupServer) SetGroupMemberInfo(ctx context.Context, req *pbGroup.SetGr return nil, err } } - err = s.GroupInterface.UpdateGroupMembers(ctx, utils.Slice(req.Members, func(e *pbGroup.SetGroupMemberInfo) *controller.BatchUpdateGroupMember { - return &controller.BatchUpdateGroupMember{ + err = s.GroupInterface.UpdateGroupMembers(ctx, utils.Slice(req.Members, func(e *pbGroup.SetGroupMemberInfo) *relationTb.BatchUpdateGroupMember { + return &relationTb.BatchUpdateGroupMember{ GroupID: e.GroupID, UserID: e.UserID, Map: UpdateGroupMemberMap(e), @@ -1053,7 +1091,7 @@ func (s *groupServer) GetGroupAbstractInfo(ctx context.Context, req *pbGroup.Get } resp.GroupAbstractInfos = utils.Slice(groups, func(group *relationTb.GroupModel) *pbGroup.GroupAbstractInfo { users := groupUserMap[group.GroupID] - return DbToPbGroupAbstractInfo(group.GroupID, uint32(len(users.UserIDs)), users.Hash) + return DbToPbGroupAbstractInfo(group.GroupID, users.MemberNum, users.Hash) }) return resp, nil } @@ -1067,7 +1105,16 @@ func (s *groupServer) GetUserInGroupMembers(ctx context.Context, req *pbGroup.Ge if err != nil { return nil, err } + nameMap, err := GetUsername(ctx, utils.Filter(members, func(e *relationTb.GroupMemberModel) (string, bool) { + return e.UserID, e.Nickname == "" + })) + if err != nil { + return nil, err + } resp.Members = utils.Slice(members, func(e *relationTb.GroupMemberModel) *open_im_sdk.GroupMemberFullInfo { + if e.Nickname == "" { + e.Nickname = nameMap[e.UserID] + } return DbToPbGroupMembersCMSResp(e) }) return resp, nil @@ -1075,10 +1122,10 @@ func (s *groupServer) GetUserInGroupMembers(ctx context.Context, req *pbGroup.Ge func (s *groupServer) GetGroupMemberUserID(ctx context.Context, req *pbGroup.GetGroupMemberUserIDReq) (*pbGroup.GetGroupMemberUserIDResp, error) { resp := &pbGroup.GetGroupMemberUserIDResp{} - userIDs, err := s.GroupInterface.FindGroupMemberUserID(ctx, req.GroupID) + var err error + resp.UserIDs, err = s.GroupInterface.FindGroupMemberUserID(ctx, req.GroupID) if err != nil { return nil, err } - resp.UserIDs = userIDs return resp, nil } diff --git a/pkg/common/db/cache/group.go b/pkg/common/db/cache/group.go index c5a9ef51b..8376a1d56 100644 --- a/pkg/common/db/cache/group.go +++ b/pkg/common/db/cache/group.go @@ -1,7 +1,6 @@ package cache import ( - "Open_IM/pkg/common/constant" "Open_IM/pkg/common/db/relation" relationTb "Open_IM/pkg/common/db/table/relation" "Open_IM/pkg/common/db/unrelation" @@ -12,8 +11,8 @@ import ( "github.com/dtm-labs/rockscache" "github.com/go-redis/redis/v8" "math/big" - "sort" "strconv" + "strings" "time" ) @@ -117,22 +116,6 @@ func (g *GroupCacheRedis) GetGroupInfo(ctx context.Context, groupID string) (gro }) } -func (g *GroupCacheRedis) DelGroupInfo(ctx context.Context, groupID string) (err error) { - defer func() { - tracelog.SetCtxDebug(ctx, utils.GetFuncName(1), err, "groupID", groupID) - }() - return g.rcClient.TagAsDeleted(g.getGroupInfoKey(groupID)) -} - -func (g *GroupCacheRedis) DelGroupsInfo(ctx context.Context, groupIDs []string) error { - for _, groupID := range groupIDs { - if err := g.DelGroupInfo(ctx, groupID); err != nil { - return err - } - } - return nil -} - // userJoinSuperGroup func (g *GroupCacheRedis) BatchDelJoinedSuperGroupIDs(ctx context.Context, userIDs []string) (err error) { for _, userID := range userIDs { @@ -160,43 +143,18 @@ func (g *GroupCacheRedis) GetJoinedSuperGroupIDs(ctx context.Context, userID str }) } -//// groupMembersHash -//func (g *GroupCacheRedis) GetGroupsMembersHash(ctx context.Context, groupIDs []string) (map[string]uint64, error) { -// return GetCache(ctx, g.rcClient, g.getGroupMembersHashKey(groupID), g.expireTime, "") -//} - // groupMembersHash func (g *GroupCacheRedis) GetGroupMembersHash(ctx context.Context, groupID string) (hashCodeUint64 uint64, err error) { - generateHash := func() (string, error) { - groupInfo, err := g.GetGroupInfo(ctx, groupID) + return GetCache(ctx, g.rcClient, g.getGroupMembersHashKey(groupID), g.expireTime, func(ctx context.Context) (uint64, error) { + userIDs, err := g.GetGroupMemberIDs(ctx, groupID) if err != nil { - return "", err - } - if groupInfo.Status == constant.GroupStatusDismissed { - return "0", nil - } - groupMemberIDList, err := g.GetGroupMemberIDs(ctx, groupID) - if err != nil { - return "", err - } - sort.Strings(groupMemberIDList) - var all string - for _, v := range groupMemberIDList { - all += v + return 0, err } + utils.Sort(userIDs, true) bi := big.NewInt(0) - bi.SetString(utils.Md5(all)[0:8], 16) - return strconv.Itoa(int(bi.Uint64())), nil - } - defer func() { - tracelog.SetCtxDebug(ctx, utils.GetFuncName(1), err, "groupID", groupID, "hashCodeUint64", hashCodeUint64) - }() - hashCodeStr, err := g.rcClient.Fetch(g.getGroupMembersHashKey(groupID), time.Second*30*60, generateHash) - if err != nil { - return 0, utils.Wrap(err, "fetch failed") - } - hashCode, err := strconv.Atoi(hashCodeStr) - return uint64(hashCode), err + bi.SetString(utils.Md5(strings.Join(userIDs, ";"))[0:8], 16) + return bi.Uint64(), nil + }) } func (g *GroupCacheRedis) DelGroupMembersHash(ctx context.Context, groupID string) (err error) { @@ -207,41 +165,10 @@ func (g *GroupCacheRedis) DelGroupMembersHash(ctx context.Context, groupID strin } // groupMemberIDs -// from redis func (g *GroupCacheRedis) GetGroupMemberIDs(ctx context.Context, groupID string) (groupMemberIDs []string, err error) { - f := func() (string, error) { - groupInfo, err := g.GetGroupInfo(ctx, groupID) - if err != nil { - return "", err - } - var groupMemberIDList []string - if groupInfo.GroupType == constant.SuperGroup { - superGroup, err := g.mongoDB.GetSuperGroup(ctx, groupID) - if err != nil { - return "", err - } - groupMemberIDList = superGroup.MemberIDList - } else { - groupMemberIDList, err = relation.GetGroupMemberIDListByGroupID(groupID) - if err != nil { - return "", err - } - } - bytes, err := json.Marshal(groupMemberIDList) - if err != nil { - return "", utils.Wrap(err, "") - } - return string(bytes), nil - } - defer func() { - tracelog.SetCtxDebug(ctx, utils.GetFuncName(1), err, "groupID", groupID, "groupMemberIDList", groupMemberIDs) - }() - groupIDListStr, err := g.rcClient.Fetch(g.getGroupMemberIDsKey(groupID), time.Second*30*60, f) - if err != nil { - return nil, err - } - err = json.Unmarshal([]byte(groupIDListStr), &groupMemberIDs) - return groupMemberIDs, nil + return GetCache(ctx, g.rcClient, g.getGroupMemberIDsKey(groupID), g.expireTime, func(ctx context.Context) ([]string, error) { + return g.groupMember.FindMemberUserID(ctx, groupID) + }) } func (g *GroupCacheRedis) DelGroupMemberIDs(ctx context.Context, groupID string) (err error) { @@ -389,3 +316,19 @@ func (g *GroupCacheRedis) DelGroupMemberNum(ctx context.Context, groupID string) }() return g.rcClient.TagAsDeleted(g.getGroupMemberNumKey(groupID)) } + +func (g *GroupCacheRedis) DelGroupInfo(ctx context.Context, groupID string) (err error) { + defer func() { + tracelog.SetCtxDebug(ctx, utils.GetFuncName(1), err, "groupID", groupID) + }() + return g.rcClient.TagAsDeleted(g.getGroupInfoKey(groupID)) +} + +func (g *GroupCacheRedis) DelGroupsInfo(ctx context.Context, groupIDs []string) error { + for _, groupID := range groupIDs { + if err := g.DelGroupInfo(ctx, groupID); err != nil { + return err + } + } + return nil +} diff --git a/pkg/common/db/controller/group.go b/pkg/common/db/controller/group.go index 96085d128..ba39bb511 100644 --- a/pkg/common/db/controller/group.go +++ b/pkg/common/db/controller/group.go @@ -21,17 +21,6 @@ import ( //type GroupInterface GroupDataBaseInterface -type BatchUpdateGroupMember struct { - GroupID string - UserID string - Map map[string]any -} - -type GroupSimpleUserID struct { - Hash uint64 - UserIDs []string -} - type GroupInterface interface { CreateGroup(ctx context.Context, groups []*relationTb.GroupModel, groupMembers []*relationTb.GroupMemberModel) error TakeGroup(ctx context.Context, groupID string) (group *relationTb.GroupModel, err error) @@ -48,11 +37,11 @@ type GroupInterface interface { SearchGroupMember(ctx context.Context, keyword string, groupIDs []string, userIDs []string, roleLevels []int32, pageNumber, showNumber int32) (uint32, []*relationTb.GroupMemberModel, error) HandlerGroupRequest(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32, member *relationTb.GroupMemberModel) error DeleteGroupMember(ctx context.Context, groupID string, userIDs []string) error - MapGroupMemberUserID(ctx context.Context, groupIDs []string) (map[string]*GroupSimpleUserID, error) + MapGroupMemberUserID(ctx context.Context, groupIDs []string) (map[string]*relationTb.GroupSimpleUserID, error) MapGroupMemberNum(ctx context.Context, groupIDs []string) (map[string]uint32, error) TransferGroupOwner(ctx context.Context, groupID string, oldOwnerUserID, newOwnerUserID string, roleLevel int32) error // 转让群 UpdateGroupMember(ctx context.Context, groupID string, userID string, data map[string]any) error - UpdateGroupMembers(ctx context.Context, data []*BatchUpdateGroupMember) error + UpdateGroupMembers(ctx context.Context, data []*relationTb.BatchUpdateGroupMember) error // GroupRequest CreateGroupRequest(ctx context.Context, requests []*relationTb.GroupRequestModel) error TakeGroupRequest(ctx context.Context, groupID string, userID string) (*relationTb.GroupRequestModel, error) @@ -132,7 +121,7 @@ func (g *GroupController) DeleteGroupMember(ctx context.Context, groupID string, return g.database.DeleteGroupMember(ctx, groupID, userIDs) } -func (g *GroupController) MapGroupMemberUserID(ctx context.Context, groupIDs []string) (map[string]*GroupSimpleUserID, error) { +func (g *GroupController) MapGroupMemberUserID(ctx context.Context, groupIDs []string) (map[string]*relationTb.GroupSimpleUserID, error) { return g.database.MapGroupMemberUserID(ctx, groupIDs) } @@ -144,7 +133,7 @@ func (g *GroupController) TransferGroupOwner(ctx context.Context, groupID string return g.database.TransferGroupOwner(ctx, groupID, oldOwnerUserID, newOwnerUserID, roleLevel) } -func (g *GroupController) UpdateGroupMembers(ctx context.Context, data []*BatchUpdateGroupMember) error { +func (g *GroupController) UpdateGroupMembers(ctx context.Context, data []*relationTb.BatchUpdateGroupMember) error { return g.database.UpdateGroupMembers(ctx, data) } @@ -204,11 +193,11 @@ type GroupDataBaseInterface interface { SearchGroupMember(ctx context.Context, keyword string, groupIDs []string, userIDs []string, roleLevels []int32, pageNumber, showNumber int32) (uint32, []*relationTb.GroupMemberModel, error) HandlerGroupRequest(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32, member *relationTb.GroupMemberModel) error DeleteGroupMember(ctx context.Context, groupID string, userIDs []string) error - MapGroupMemberUserID(ctx context.Context, groupIDs []string) (map[string]*GroupSimpleUserID, error) + MapGroupMemberUserID(ctx context.Context, groupIDs []string) (map[string]*relationTb.GroupSimpleUserID, error) MapGroupMemberNum(ctx context.Context, groupIDs []string) (map[string]uint32, error) TransferGroupOwner(ctx context.Context, groupID string, oldOwnerUserID, newOwnerUserID string, roleLevel int32) error // 转让群 UpdateGroupMember(ctx context.Context, groupID string, userID string, data map[string]any) error - UpdateGroupMembers(ctx context.Context, data []*BatchUpdateGroupMember) error + UpdateGroupMembers(ctx context.Context, data []*relationTb.BatchUpdateGroupMember) error // GroupRequest CreateGroupRequest(ctx context.Context, requests []*relationTb.GroupRequestModel) error TakeGroupRequest(ctx context.Context, groupID string, userID string) (*relationTb.GroupRequestModel, error) @@ -393,20 +382,20 @@ func (g *GroupDataBase) DeleteGroupMember(ctx context.Context, groupID string, u }) } -func (g *GroupDataBase) MapGroupMemberUserID(ctx context.Context, groupIDs []string) (map[string]*GroupSimpleUserID, error) { +func (g *GroupDataBase) MapGroupMemberUserID(ctx context.Context, groupIDs []string) (map[string]*relationTb.GroupSimpleUserID, error) { mapGroupUserIDs, err := g.groupMemberDB.FindJoinUserID(ctx, groupIDs) if err != nil { return nil, err } - res := make(map[string]*GroupSimpleUserID) + res := make(map[string]*relationTb.GroupSimpleUserID) for _, groupID := range groupIDs { - users := &GroupSimpleUserID{ - UserIDs: mapGroupUserIDs[groupID], - } - if len(users.UserIDs) > 0 { - utils.Sort(users.UserIDs, true) + userIDs := mapGroupUserIDs[groupID] + users := &relationTb.GroupSimpleUserID{} + if len(userIDs) > 0 { + utils.Sort(userIDs, true) bi := big.NewInt(0) - bi.SetString(utils.Md5(strings.Join(users.UserIDs, ";"))[0:8], 16) + bi.SetString(utils.Md5(strings.Join(userIDs, ";"))[0:8], 16) + users.Hash = bi.Uint64() } res[groupID] = users } @@ -452,7 +441,7 @@ func (g *GroupDataBase) UpdateGroupMember(ctx context.Context, groupID string, u }) } -func (g *GroupDataBase) UpdateGroupMembers(ctx context.Context, data []*BatchUpdateGroupMember) error { +func (g *GroupDataBase) UpdateGroupMembers(ctx context.Context, data []*relationTb.BatchUpdateGroupMember) error { return g.db.Transaction(func(tx *gorm.DB) error { for _, item := range data { if err := g.groupMemberDB.Update(ctx, item.GroupID, item.UserID, item.Map, tx); err != nil { @@ -487,25 +476,25 @@ func (g *GroupDataBase) FindJoinSuperGroup(ctx context.Context, userID string) ( } func (g *GroupDataBase) CreateSuperGroup(ctx context.Context, groupID string, initMemberIDList []string) error { - return g.mongoDB.Transaction(ctx, func(s unrelationTb.SuperGroupModelInterface, tx any) error { - return s.CreateSuperGroup(ctx, groupID, initMemberIDList, tx) + return unrelation.MongoTransaction(ctx, g.mongoDB.MgoClient, func(tx mongo.SessionContext) error { + return g.mongoDB.CreateSuperGroup(ctx, groupID, initMemberIDList, tx) }) } func (g *GroupDataBase) DeleteSuperGroup(ctx context.Context, groupID string) error { - return g.mongoDB.Transaction(ctx, func(s unrelationTb.SuperGroupModelInterface, tx any) error { - return s.DeleteSuperGroup(ctx, groupID, tx) + return unrelation.MongoTransaction(ctx, g.mongoDB.MgoClient, func(tx mongo.SessionContext) error { + return g.mongoDB.DeleteSuperGroup(ctx, groupID, tx) }) } func (g *GroupDataBase) DeleteSuperGroupMember(ctx context.Context, groupID string, userIDs []string) error { - return g.mongoDB.Transaction(ctx, func(s unrelationTb.SuperGroupModelInterface, tx any) error { - return s.RemoverUserFromSuperGroup(ctx, groupID, userIDs, tx) + return unrelation.MongoTransaction(ctx, g.mongoDB.MgoClient, func(tx mongo.SessionContext) error { + return g.mongoDB.RemoverUserFromSuperGroup(ctx, groupID, userIDs, tx) }) } func (g *GroupDataBase) CreateSuperGroupMember(ctx context.Context, groupID string, userIDs []string) error { - return g.mongoDB.Transaction(ctx, func(s unrelationTb.SuperGroupModelInterface, tx any) error { - return s.AddUserToSuperGroup(ctx, groupID, userIDs, tx) + return unrelation.MongoTransaction(ctx, g.mongoDB.MgoClient, func(tx mongo.SessionContext) error { + return g.mongoDB.AddUserToSuperGroup(ctx, groupID, userIDs, tx) }) } diff --git a/pkg/common/db/table/relation/utils.go b/pkg/common/db/table/relation/utils.go new file mode 100644 index 000000000..a046de1e8 --- /dev/null +++ b/pkg/common/db/table/relation/utils.go @@ -0,0 +1,12 @@ +package relation + +type BatchUpdateGroupMember struct { + GroupID string + UserID string + Map map[string]any +} + +type GroupSimpleUserID struct { + Hash uint64 + MemberNum uint32 +} diff --git a/pkg/utils/utils_v2.go b/pkg/utils/utils_v2.go index c01103bfa..91c8fecd9 100644 --- a/pkg/utils/utils_v2.go +++ b/pkg/utils/utils_v2.go @@ -144,11 +144,12 @@ func SliceSetAny[E any, K comparable](es []E, fn func(e E) K) map[K]struct{} { }) } -func Filter[E any](es []E, fn func(e E) bool) []E { - rs := make([]E, 0, len(es)) +func Filter[E, T any](es []E, fn func(e E) (T, bool)) []T { + rs := make([]T, 0, len(es)) for i := 0; i < len(es); i++ { - if e := es[i]; fn(e) { - rs = append(rs, e) + e := es[i] + if t, ok := fn(e); ok { + rs = append(rs, t) } } return rs