Files
open-im-server/pkg/common/db/cache/group.go
T

419 lines
14 KiB
Go
Raw Normal View History

2023-01-17 14:40:20 +08:00
package cache
import (
2023-01-31 18:55:22 +08:00
"Open_IM/pkg/common/constant"
2023-01-28 13:19:36 +08:00
"Open_IM/pkg/common/db/relation"
2023-02-09 10:55:21 +08:00
relationTb "Open_IM/pkg/common/db/table/relation"
2023-01-31 18:55:22 +08:00
"Open_IM/pkg/common/db/unrelation"
2023-01-30 11:14:18 +08:00
"Open_IM/pkg/common/tracelog"
2023-01-17 14:40:20 +08:00
"Open_IM/pkg/utils"
"context"
"encoding/json"
"github.com/dtm-labs/rockscache"
"github.com/go-redis/redis/v8"
2023-01-31 18:55:22 +08:00
"math/big"
"sort"
"strconv"
2023-01-17 14:40:20 +08:00
"time"
)
2023-01-31 18:55:22 +08:00
const (
groupExpireTime = time.Second * 60 * 60 * 12
groupInfoKey = "GROUP_INFO:"
groupMemberIDsKey = "GROUP_MEMBER_IDS:"
groupMembersHashKey = "GROUP_MEMBERS_HASH:"
groupMemberInfoKey = "GROUP_MEMBER_INFO:"
joinedSuperGroupsKey = "JOIN_SUPER_GROUPS:"
joinedGroupsKey = "JOIN_GROUPS_KEY:"
groupMemberNumKey = "GROUP_MEMBER_NUM_CACHE:"
)
2023-01-17 14:40:20 +08:00
2023-02-09 10:55:21 +08:00
type GroupCache interface {
GetGroupsInfo(ctx context.Context, groupIDs []string, fn func(ctx context.Context, groupIDs []string) (groups []*relationTb.GroupModel, err error)) (groups []*relationTb.GroupModel, err error)
DelGroupsInfo(ctx context.Context, groupID string) (err error)
GetGroupInfo(ctx context.Context, groupID string, fn func(ctx context.Context, groupID string) (group *relationTb.GroupModel, err error)) (group *relationTb.GroupModel, err error)
DelGroupInfo(ctx context.Context, groupID string) (err error)
2023-02-09 16:11:18 +08:00
BatchDelJoinedSuperGroupIDs(ctx context.Context, userIDs []string, fn func(ctx context.Context, userIDs []string) error) (err error)
GetJoinedSuperGroupIDs(ctx context.Context, userID string, fn func(ctx context.Context, userID string) (joinedSuperGroupIDs []string, err error)) (joinedSuperGroupIDs []string, err error)
DelJoinedSuperGroupIDs(ctx context.Context, userID string, fn func(ctx context.Context, userID string) error) (err error)
GetGroupMembersHash(ctx context.Context, groupID string, fn func(ctx context.Context, groupID string) (hashCodeUint64 uint64, err error)) (hashCodeUint64 uint64, err error)
DelGroupMembersHash(ctx context.Context, groupID string) (err error)
GetGroupMemberIDs(ctx context.Context, groupID string, fn func(ctx context.Context, groupID string) (groupMemberIDs []string, err error)) (groupMemberIDs []string, err error)
DelGroupMemberIDs(ctx context.Context, groupID string)
GetJoinedGroupIDs(ctx context.Context, userID string, fn func(ctx context.Context, userID string) (joinedGroupIDs []string, err error)) (joinedGroupIDs []string, err error)
DelJoinedGroupIDs(ctx context.Context, userID string) (err error)
GetGroupMemberInfo(ctx context.Context, groupID, userID string, fn func(ctx context.Context, groupID, userID string) (groupMember *relationTb.GroupMemberModel, err error)) (groupMember *relationTb.GroupMemberModel, err error)
GetGroupMembersInfo(ctx context.Context, count, offset int32, groupID string, fn func(ctx context.Context, count, offset int32, groupID string) (groupMembers []*relationTb.GroupMemberModel, err error)) (groupMembers []*relationTb.GroupMemberModel, err error)
DelGroupMemberInfo(ctx context.Context, groupID, userID string) (err error)
GetGroupMemberNum(ctx context.Context, groupID string, fn func(ctx context.Context, groupID string) (num int, err error)) (num int, err error)
DelGroupMemberNum(ctx context.Context, groupID string) (err error)
2023-02-09 10:55:21 +08:00
}
type GroupCacheRedis struct {
2023-02-01 17:07:56 +08:00
group *relation.GroupGorm
groupMember *relation.GroupMemberGorm
groupRequest *relation.GroupRequestGorm
2023-02-02 16:11:24 +08:00
mongoDB *unrelation.SuperGroupMongoDriver
2023-01-29 10:31:01 +08:00
expireTime time.Duration
redisClient *RedisClient
rcClient *rockscache.Client
2023-01-31 18:55:22 +08:00
}
2023-02-09 10:55:21 +08:00
func NewGroupCacheRedis(rdb redis.UniversalClient, groupDB *relation.GroupGorm, groupMemberDB *relation.GroupMemberGorm, groupRequestDB *relation.GroupRequestGorm, mongoClient *unrelation.SuperGroupMongoDriver, opts rockscache.Options) *GroupCacheRedis {
return &GroupCacheRedis{rcClient: rockscache.NewClient(rdb, opts), expireTime: groupExpireTime,
2023-01-31 18:55:22 +08:00
group: groupDB, groupMember: groupMemberDB, groupRequest: groupRequestDB, redisClient: NewRedisClient(rdb),
2023-02-02 19:43:51 +08:00
mongoDB: mongoClient,
2023-01-31 18:55:22 +08:00
}
2023-01-17 16:36:34 +08:00
}
2023-02-09 14:40:49 +08:00
func (g *GroupCacheRedis) getRedisClient() *RedisClient {
2023-01-17 16:36:34 +08:00
return g.redisClient
2023-01-17 14:40:20 +08:00
}
2023-02-09 14:40:49 +08:00
func (g *GroupCacheRedis) getGroupInfoKey(groupID string) string {
2023-01-31 18:55:22 +08:00
return groupInfoKey + groupID
}
2023-02-09 14:40:49 +08:00
func (g *GroupCacheRedis) getJoinedSuperGroupsIDKey(userID string) string {
2023-01-31 18:55:22 +08:00
return joinedSuperGroupsKey + userID
}
2023-02-09 14:40:49 +08:00
func (g *GroupCacheRedis) getJoinedGroupsKey(userID string) string {
2023-01-31 18:55:22 +08:00
return joinedGroupsKey + userID
}
2023-02-09 14:40:49 +08:00
func (g *GroupCacheRedis) getGroupMembersHashKey(groupID string) string {
2023-01-31 18:55:22 +08:00
return groupMembersHashKey + groupID
}
2023-02-09 14:40:49 +08:00
func (g *GroupCacheRedis) getGroupMemberIDsKey(groupID string) string {
2023-01-31 18:55:22 +08:00
return groupMemberIDsKey + groupID
}
2023-02-09 14:40:49 +08:00
func (g *GroupCacheRedis) getGroupMemberInfoKey(groupID, userID string) string {
2023-01-31 18:55:22 +08:00
return groupMemberInfoKey + groupID + "-" + userID
}
2023-02-09 14:40:49 +08:00
func (g *GroupCacheRedis) getGroupMemberNumKey(groupID string) string {
2023-01-31 18:55:22 +08:00
return groupMemberNumKey + groupID
}
2023-02-01 17:07:56 +08:00
// / groupInfo
2023-02-09 14:40:49 +08:00
func (g *GroupCacheRedis) GetGroupsInfo(ctx context.Context, groupIDs []string) (groups []*relation.Group, err error) {
2023-01-17 14:40:20 +08:00
for _, groupID := range groupIDs {
2023-01-29 10:31:01 +08:00
group, err := g.GetGroupInfo(ctx, groupID)
2023-01-17 14:40:20 +08:00
if err != nil {
return nil, err
}
groups = append(groups, group)
}
return groups, nil
}
2023-02-09 14:40:49 +08:00
func (g *GroupCacheRedis) GetGroupInfo(ctx context.Context, groupID string) (group *relation.GroupGorm, err error) {
2023-01-17 14:40:20 +08:00
getGroup := func() (string, error) {
2023-01-29 10:31:01 +08:00
groupInfo, err := g.group.Take(ctx, groupID)
2023-01-17 14:40:20 +08:00
if err != nil {
return "", utils.Wrap(err, "")
}
bytes, err := json.Marshal(groupInfo)
if err != nil {
return "", utils.Wrap(err, "")
}
return string(bytes), nil
}
2023-02-01 17:07:56 +08:00
group = &relation.GroupGorm{}
2023-01-17 14:40:20 +08:00
defer func() {
2023-01-30 11:10:26 +08:00
tracelog.SetCtxDebug(ctx, utils.GetFuncName(1), err, "groupID", groupID, "group", *group)
2023-01-17 14:40:20 +08:00
}()
2023-01-31 18:55:22 +08:00
groupStr, err := g.rcClient.Fetch(g.getGroupInfoKey(groupID), g.expireTime, getGroup)
2023-01-17 14:40:20 +08:00
if err != nil {
2023-01-31 18:55:22 +08:00
return nil, err
2023-01-17 14:40:20 +08:00
}
err = json.Unmarshal([]byte(groupStr), group)
return group, utils.Wrap(err, "")
}
2023-02-09 14:40:49 +08:00
func (g *GroupCacheRedis) DelGroupInfo(ctx context.Context, groupID string) (err error) {
2023-01-17 14:40:20 +08:00
defer func() {
2023-01-30 11:10:26 +08:00
tracelog.SetCtxDebug(ctx, utils.GetFuncName(1), err, "groupID", groupID)
2023-01-17 14:40:20 +08:00
}()
2023-01-31 18:55:22 +08:00
return g.rcClient.TagAsDeleted(g.getGroupInfoKey(groupID))
2023-01-17 16:36:34 +08:00
}
2023-02-09 14:40:49 +08:00
func (g *GroupCacheRedis) DelGroupsInfo(ctx context.Context, groupIDs []string) error {
2023-01-17 16:36:34 +08:00
for _, groupID := range groupIDs {
2023-01-29 10:31:01 +08:00
if err := g.DelGroupInfo(ctx, groupID); err != nil {
2023-01-17 16:36:34 +08:00
return err
}
}
return nil
2023-01-17 14:40:20 +08:00
}
2023-01-31 18:55:22 +08:00
// userJoinSuperGroup
2023-02-09 14:40:49 +08:00
func (g *GroupCacheRedis) BatchDelJoinedSuperGroupIDs(ctx context.Context, userIDs []string) (err error) {
2023-01-29 10:31:01 +08:00
for _, userID := range userIDs {
2023-01-31 18:55:22 +08:00
if err := g.DelJoinedSuperGroupIDs(ctx, userID); err != nil {
2023-01-29 10:31:01 +08:00
return err
}
}
2023-01-31 18:55:22 +08:00
return nil
}
2023-02-09 14:40:49 +08:00
func (g *GroupCacheRedis) DelJoinedSuperGroupIDs(ctx context.Context, userID string) (err error) {
2023-01-31 18:55:22 +08:00
defer func() {
tracelog.SetCtxDebug(ctx, utils.GetFuncName(1), err, "userID", userID)
}()
return g.rcClient.TagAsDeleted(g.getJoinedSuperGroupsIDKey(userID))
}
2023-02-09 14:40:49 +08:00
func (g *GroupCacheRedis) GetJoinedSuperGroupIDs(ctx context.Context, userID string) (joinedSuperGroupIDs []string, err error) {
2023-01-31 18:55:22 +08:00
getJoinedSuperGroupIDList := func() (string, error) {
userToSuperGroup, err := g.mongoDB.GetSuperGroupByUserID(ctx, userID)
if err != nil {
return "", err
}
bytes, err := json.Marshal(userToSuperGroup.GroupIDList)
if err != nil {
return "", utils.Wrap(err, "")
}
return string(bytes), nil
}
defer func() {
tracelog.SetCtxDebug(ctx, utils.GetFuncName(1), err, "userID", userID, "joinedSuperGroupIDs", joinedSuperGroupIDs)
}()
joinedSuperGroupListStr, err := g.rcClient.Fetch(g.getJoinedSuperGroupsIDKey(userID), time.Second*30*60, getJoinedSuperGroupIDList)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(joinedSuperGroupListStr), &joinedSuperGroupIDs)
return joinedSuperGroupIDs, utils.Wrap(err, "")
}
// groupMembersHash
2023-02-09 14:40:49 +08:00
func (g *GroupCacheRedis) GetGroupMembersHash(ctx context.Context, groupID string) (hashCodeUint64 uint64, err error) {
2023-01-31 18:55:22 +08:00
generateHash := func() (string, error) {
groupInfo, err := g.GetGroupInfo(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
}
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
}
2023-02-09 14:40:49 +08:00
func (g *GroupCacheRedis) DelGroupMembersHash(ctx context.Context, groupID string) (err error) {
2023-01-31 18:55:22 +08:00
defer func() {
tracelog.SetCtxDebug(ctx, utils.GetFuncName(1), err, "groupID", groupID)
}()
return g.rcClient.TagAsDeleted(g.getGroupMembersHashKey(groupID))
}
// groupMemberIDs
// from redis
2023-02-09 14:40:49 +08:00
func (g *GroupCacheRedis) GetGroupMemberIDs(ctx context.Context, groupID string) (groupMemberIDs []string, err error) {
2023-01-31 18:55:22 +08:00
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
2023-01-29 10:31:01 +08:00
}
2023-02-09 14:40:49 +08:00
func (g *GroupCacheRedis) DelGroupMemberIDs(ctx context.Context, groupID string) (err error) {
2023-01-31 18:55:22 +08:00
defer func() {
tracelog.SetCtxDebug(ctx, utils.GetFuncName(1), err, "groupID", groupID)
}()
return g.rcClient.TagAsDeleted(g.getGroupMemberIDsKey(groupID))
}
// JoinedGroups
2023-02-09 14:40:49 +08:00
func (g *GroupCacheRedis) GetJoinedGroupIDs(ctx context.Context, userID string) (joinedGroupIDs []string, err error) {
2023-01-31 18:55:22 +08:00
getJoinedGroupIDList := func() (string, error) {
joinedGroupList, err := relation.GetJoinedGroupIDListByUserID(userID)
if err != nil {
return "", err
}
bytes, err := json.Marshal(joinedGroupList)
if err != nil {
return "", utils.Wrap(err, "")
}
return string(bytes), nil
}
defer func() {
tracelog.SetCtxDebug(ctx, utils.GetFuncName(1), err, "userID", userID, "joinedGroupIDs", joinedGroupIDs)
}()
joinedGroupIDListStr, err := g.rcClient.Fetch(g.getJoinedGroupsKey(userID), time.Second*30*60, getJoinedGroupIDList)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(joinedGroupIDListStr), &joinedGroupIDs)
return joinedGroupIDs, utils.Wrap(err, "")
}
2023-02-09 14:40:49 +08:00
func (g *GroupCacheRedis) DelJoinedGroupIDs(ctx context.Context, userID string) (err error) {
2023-01-29 10:31:01 +08:00
defer func() {
2023-01-30 11:10:26 +08:00
tracelog.SetCtxDebug(ctx, utils.GetFuncName(1), err, "userID", userID)
2023-01-29 10:31:01 +08:00
}()
2023-01-31 18:55:22 +08:00
return g.rcClient.TagAsDeleted(g.getJoinedGroupsKey(userID))
}
// GetGroupMemberInfo
2023-02-09 14:40:49 +08:00
func (g *GroupCacheRedis) GetGroupMemberInfo(ctx context.Context, groupID, userID string) (groupMember *relation.GroupMember, err error) {
2023-01-31 18:55:22 +08:00
getGroupMemberInfo := func() (string, error) {
groupMemberInfo, err := relation.GetGroupMemberInfoByGroupIDAndUserID(groupID, userID)
if err != nil {
return "", err
}
bytes, err := json.Marshal(groupMemberInfo)
if err != nil {
return "", utils.Wrap(err, "")
}
return string(bytes), nil
}
defer func() {
tracelog.SetCtxDebug(ctx, utils.GetFuncName(1), err, "groupID", groupID, "userID", userID, "groupMember", *groupMember)
}()
groupMemberInfoStr, err := g.rcClient.Fetch(g.getGroupMemberInfoKey(groupID, userID), time.Second*30*60, getGroupMemberInfo)
if err != nil {
return nil, err
}
groupMember = &relation.GroupMember{}
err = json.Unmarshal([]byte(groupMemberInfoStr), groupMember)
return groupMember, utils.Wrap(err, "")
}
2023-02-09 14:40:49 +08:00
func (g *GroupCacheRedis) GetGroupMembersInfo(ctx context.Context, count, offset int32, groupID string) (groupMembers []*relation.GroupMember, err error) {
2023-02-01 11:23:01 +08:00
defer func() {
tracelog.SetCtxDebug(ctx, utils.GetFuncName(1), err, "count", count, "offset", offset, "groupID", groupID, "groupMember", groupMembers)
}()
groupMemberIDList, err := g.GetGroupMemberIDs(ctx, groupID)
if err != nil {
return nil, err
}
if count < 0 || offset < 0 {
return nil, nil
}
var groupMemberList []*relation.GroupMember
var start, stop int32
start = offset
stop = offset + count
l := int32(len(groupMemberIDList))
if start > stop {
return nil, nil
}
if start >= l {
return nil, nil
}
if count != 0 {
if stop >= l {
stop = l
}
groupMemberIDList = groupMemberIDList[start:stop]
} else {
if l < 1000 {
stop = l
} else {
stop = 1000
}
groupMemberIDList = groupMemberIDList[start:stop]
}
for _, userID := range groupMemberIDList {
groupMember, err := g.GetGroupMemberInfo(ctx, groupID, userID)
if err != nil {
return
}
groupMembers = append(groupMembers, groupMember)
}
return groupMemberList, nil
}
2023-02-09 14:40:49 +08:00
func (g *GroupCacheRedis) DelGroupMemberInfo(ctx context.Context, groupID, userID string) (err error) {
2023-01-31 18:55:22 +08:00
defer func() {
tracelog.SetCtxDebug(ctx, utils.GetFuncName(1), err, "groupID", groupID, "userID", userID)
}()
return g.rcClient.TagAsDeleted(g.getGroupMemberInfoKey(groupID, userID))
}
// groupMemberNum
2023-02-09 14:40:49 +08:00
func (g *GroupCacheRedis) GetGroupMemberNum(ctx context.Context, groupID string) (num int, err error) {
2023-01-31 18:55:22 +08:00
getGroupMemberNum := func() (string, error) {
num, err := relation.GetGroupMemberNumByGroupID(groupID)
if err != nil {
return "", err
}
return strconv.Itoa(int(num)), nil
}
defer func() {
tracelog.SetCtxDebug(ctx, utils.GetFuncName(1), err, "groupID", groupID, "num", num)
}()
groupMember, err := g.rcClient.Fetch(g.getGroupMemberNumKey(groupID), time.Second*30*60, getGroupMemberNum)
if err != nil {
return 0, err
}
return strconv.Atoi(groupMember)
}
2023-02-09 14:40:49 +08:00
func (g *GroupCacheRedis) DelGroupMemberNum(ctx context.Context, groupID string) (err error) {
2023-01-31 18:55:22 +08:00
defer func() {
tracelog.SetCtxDebug(ctx, utils.GetFuncName(1), err, "groupID", groupID)
}()
return g.rcClient.TagAsDeleted(g.getGroupMemberNumKey(groupID))
2023-01-29 10:31:01 +08:00
}