Skip to content

Commit

Permalink
Merge pull request #6 from icey-yu/fix-cache
Browse files Browse the repository at this point in the history
Fix cache
  • Loading branch information
icey-yu committed Sep 14, 2024
2 parents 1dc9a43 + 1b71a2c commit 1f2f88e
Show file tree
Hide file tree
Showing 11 changed files with 207 additions and 134 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ require golang.org/x/net v0.22.0 // indirect
require (
github.com/google/go-cmp v0.6.0
github.com/openimsdk/protocol v0.0.72-alpha.12
github.com/openimsdk/tools v0.0.50-alpha.9
github.com/openimsdk/tools v0.0.50-alpha.14
github.com/patrickmn/go-cache v2.1.0+incompatible
golang.org/x/image v0.15.0
golang.org/x/sync v0.6.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/openimsdk/protocol v0.0.72-alpha.12 h1:GXUtSFXlh1AeOmMjN1CsRfRZMTQYBWZ8mTuRoB7KxLQ=
github.com/openimsdk/protocol v0.0.72-alpha.12/go.mod h1:OZQA9FR55lseYoN2Ql1XAHYKHJGu7OMNkUbuekrKCM8=
github.com/openimsdk/tools v0.0.50-alpha.9 h1:oeFFjDdgHyGM+2QUr0j0uiFEiiFtda+rr7lm+0fLmHA=
github.com/openimsdk/tools v0.0.50-alpha.9/go.mod h1:oiSQU5Z6fzjxKFjbqDHImD8EmCIwClU1Rkur1sK12Po=
github.com/openimsdk/tools v0.0.50-alpha.14 h1:7mqOwJWHcG181KvkmU+oJn9ZpYNoUykt9WtuOQg4sDU=
github.com/openimsdk/tools v0.0.50-alpha.14/go.mod h1:h1cYmfyaVtgFbKmb1Cfsl8XwUOMTt8ubVUQrdGtsUh4=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
Expand Down
8 changes: 1 addition & 7 deletions internal/conversation_msg/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -985,13 +985,7 @@ func (c *Conversation) initBasicInfo(ctx context.Context, message *sdk_struct.Ms
message.IsRead = false
message.Status = constant.MsgStatusSending
message.SendID = c.loginUserID
userInfo, err := c.user.GetUserInfoWithCache(ctx, c.loginUserID, func(ctx context.Context, key string) (*model_struct.LocalUser, error) {
info, err := c.db.GetLoginUser(ctx, key)
if err != nil {
return nil, err
}
return info, nil
})
userInfo, err := c.user.GetUserInfoWithCacheFunc(ctx, c.loginUserID, c.db.GetLoginUser)
if err != nil {
return err
}
Expand Down
20 changes: 2 additions & 18 deletions internal/conversation_msg/conversation_msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/db_interface"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/openim-sdk-core/v3/pkg/page"
"github.com/openimsdk/openim-sdk-core/v3/pkg/sdkerrs"
"github.com/openimsdk/openim-sdk-core/v3/pkg/syncer"
pbConversation "github.com/openimsdk/protocol/conversation"
"github.com/openimsdk/protocol/sdkws"
Expand Down Expand Up @@ -979,13 +978,7 @@ func (c *Conversation) batchGetUserNameAndFaceURL(ctx context.Context, userIDs .
}
m[localFriend.FriendUserID] = userInfo
}
usersInfo, err := c.user.GetUsersInfoWithCache(ctx, notInFriend, func(ctx context.Context, missingKeys []string) ([]*model_struct.LocalUser, error) {
users, err := c.user.GetUserInfoFromServer(ctx, missingKeys)
if err != nil {
return nil, err
}
return users, nil
})
usersInfo, err := c.user.GetUsersInfoWithCache(ctx, notInFriend)
if err != nil {
return nil, err
}
Expand All @@ -1006,16 +999,7 @@ func (c *Conversation) getUserNameAndFaceURL(ctx context.Context, userID string)
}
return faceURL, name, nil
}
userInfo, err := c.user.GetUserInfoWithCache(ctx, userID, func(ctx context.Context, key string) (*model_struct.LocalUser, error) {
users, err := c.user.GetUserInfoFromServer(ctx, []string{userID})
if err != nil {
return nil, err
}
if len(users) > 0 {
return users[0], nil
}
return nil, sdkerrs.ErrUserIDNotFound.Wrap()
})
userInfo, err := c.user.GetUserInfoWithCache(ctx, userID)
if err != nil {
return "", "", nil
}
Expand Down
59 changes: 2 additions & 57 deletions internal/group/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ import (
"context"
"time"

"github.com/openimsdk/openim-sdk-core/v3/pkg/cache"
"github.com/openimsdk/openim-sdk-core/v3/sdk_struct"

"github.com/openimsdk/tools/errs"

"github.com/openimsdk/tools/utils/datautil"
Expand Down Expand Up @@ -524,60 +521,8 @@ func (g *Group) HandlerGroupApplication(ctx context.Context, req *group.GroupApp
return nil
}

func (g *Group) GetGroupMemberNameAndFaceURL(ctx context.Context, groupID string, userIDs []string) (map[string]*sdk_struct.BasicInfo, error) {
memberInfo, err := g.db.GetGroupSomeMemberInfo(ctx, groupID, userIDs)
if err != nil {
return nil, err
}
res := datautil.SliceToMapAny(memberInfo, func(e *model_struct.LocalGroupMember) (string, *sdk_struct.BasicInfo) {
return e.UserID, &sdk_struct.BasicInfo{
Nickname: e.Nickname,
FaceURL: e.FaceURL,
}
})
unFind := datautil.SliceSubAny(userIDs, memberInfo, func(t *model_struct.LocalGroupMember) string {
return t.UserID
})

queryUserIDs := make([]string, 0)

var (
groupMap *cache.Cache[string, *sdk_struct.BasicInfo]
ok bool
)

if groupMap, ok = g.groupMemberCache.Load(groupID); ok {
for _, userID := range unFind {
if data, ok := groupMap.Load(userID); ok {
res[userID] = data
} else {
queryUserIDs = append(queryUserIDs, userID)
}
}
} else {
groupMap = cache.NewCache[string, *sdk_struct.BasicInfo]()
queryUserIDs = append(queryUserIDs, unFind...)
}

if len(queryUserIDs) != 0 {
members, err := g.GetDesignatedGroupMembers(ctx, groupID, queryUserIDs)
if err != nil {
return nil, err
}

for _, member := range members {
info := &sdk_struct.BasicInfo{
Nickname: member.Nickname,
FaceURL: member.FaceURL,
}

res[member.UserID] = info
groupMap.Store(member.UserID, info)
}
g.groupMemberCache.Store(groupID, groupMap)
}

return res, nil
func (g *Group) GetGroupMemberNameAndFaceURL(ctx context.Context, groupID string, userIDs []string) (map[string]*model_struct.LocalGroupMember, error) {
return g.GetGroupMembersInfo(ctx, groupID, userIDs)
}

//func (g *Group) SearchGroupMembersV2(ctx context.Context, req *group.SearchGroupMemberReq) ([]*model_struct.LocalGroupMember, error) {
Expand Down
66 changes: 66 additions & 0 deletions internal/group/cache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package group

import (
"context"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/tools/utils/datautil"
)

func (g *Group) buildGroupMemberKey(groupID string, userID string) string {
return groupID + ":" + userID
}

func (g *Group) GetGroupMembersInfoFunc(ctx context.Context, groupID string, userIDs []string,
fetchFunc func(ctx context.Context, missingKeys []string) ([]*model_struct.LocalGroupMember, error),
) (map[string]*model_struct.LocalGroupMember, error) {
var (
res = make(map[string]*model_struct.LocalGroupMember)
missingKeys []string
)

for _, userID := range userIDs {
key := g.buildGroupMemberKey(groupID, userID)
if member, ok := g.groupMemberCache.Load(groupID); ok {
res[key] = member
} else {
missingKeys = append(missingKeys, userIDs...)
}
}

fetchData, err := fetchFunc(ctx, missingKeys)
if err != nil {
return nil, err
}

for i, data := range fetchData {
key := g.buildGroupMemberKey(groupID, data.UserID)
res[key] = fetchData[i]
g.groupMemberCache.Store(key, fetchData[i])
}

return res, nil
}

func (g *Group) GetGroupMembersInfo(ctx context.Context, groupID string, userIDs []string) (map[string]*model_struct.LocalGroupMember, error) {
return g.GetGroupMembersInfoFunc(ctx, groupID, userIDs, func(ctx context.Context, dbKeys []string) ([]*model_struct.LocalGroupMember, error) {
if len(dbKeys) == 0 {
return nil, nil
}
dbData, err := g.db.GetGroupSomeMemberInfo(ctx, groupID, dbKeys)
if err != nil {
return nil, err
}
queryKeys := datautil.SliceSubAny(dbKeys, dbData, func(t *model_struct.LocalGroupMember) string {
return t.UserID
})
if len(queryKeys) != 0 {
queryData, err := g.GetDesignatedGroupMembers(ctx, groupID, queryKeys)
if err != nil {
return nil, err
}

dbData = append(dbData, datautil.Batch(ServerGroupMemberToLocalGroupMember, queryData)...)
}
return dbData, nil
})
}
12 changes: 5 additions & 7 deletions internal/group/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,16 @@ import (
"context"
"sync"

"github.com/openimsdk/openim-sdk-core/v3/open_im_sdk_callback"
"github.com/openimsdk/openim-sdk-core/v3/pkg/api"
"github.com/openimsdk/openim-sdk-core/v3/pkg/cache"
"github.com/openimsdk/openim-sdk-core/v3/pkg/datafetcher"
"github.com/openimsdk/openim-sdk-core/v3/pkg/sdkerrs"
"github.com/openimsdk/openim-sdk-core/v3/sdk_struct"

"github.com/openimsdk/openim-sdk-core/v3/open_im_sdk_callback"
"github.com/openimsdk/openim-sdk-core/v3/pkg/common"
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
"github.com/openimsdk/openim-sdk-core/v3/pkg/datafetcher"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/db_interface"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/openim-sdk-core/v3/pkg/page"
"github.com/openimsdk/openim-sdk-core/v3/pkg/sdkerrs"
"github.com/openimsdk/openim-sdk-core/v3/pkg/syncer"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
"github.com/openimsdk/protocol/group"
Expand All @@ -51,7 +49,7 @@ func NewGroup(loginUserID string, db db_interface.DataBase,
conversationCh: conversationCh,
}
g.initSyncer()
g.groupMemberCache = cache.NewCache[string, *cache.Cache[string, *sdk_struct.BasicInfo]]()
g.groupMemberCache = cache.NewCache[string, *model_struct.LocalGroupMember]()
return g
}

Expand All @@ -70,7 +68,7 @@ type Group struct {
groupSyncMutex sync.Mutex
listenerForService open_im_sdk_callback.OnListenerForService

groupMemberCache *cache.Cache[string, *cache.Cache[string, *sdk_struct.BasicInfo]]
groupMemberCache *cache.Cache[string, *model_struct.LocalGroupMember]
}

func (g *Group) initSyncer() {
Expand Down
8 changes: 1 addition & 7 deletions internal/user/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,7 @@ func (u *User) GetUserInfoFromServer(ctx context.Context, userIDs []string) ([]*
}

func (u *User) GetUsersInfo(ctx context.Context, userIDs []string) ([]*sdk_struct.PublicUser, error) {
usersInfo, err := u.GetUsersInfoWithCache(ctx, userIDs, func(ctx context.Context, missingKeys []string) ([]*model_struct.LocalUser, error) {
users, err := u.GetUserInfoFromServer(ctx, missingKeys)
if err != nil {
return nil, err
}
return users, nil
})
usersInfo, err := u.GetUsersInfoWithCache(ctx, userIDs)
if err != nil {
return nil, err
}
Expand Down
48 changes: 17 additions & 31 deletions internal/user/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,12 @@ import (
func NewUser(dataBase db_interface.DataBase, loginUserID string, conversationCh chan common.Cmd2Value) *User {
user := &User{DataBase: dataBase, loginUserID: loginUserID, conversationCh: conversationCh}
user.initSyncer()
user.UserCache = cache.NewCache[string, *model_struct.LocalUser]()
//user.OnlineStatusCache = cache.NewCache[string, *userPb.OnlineStatus]()
user.UserCache = cache.NewManager[string, *model_struct.LocalUser](
func(value *model_struct.LocalUser) string { return value.UserID },
nil,
user.GetUserInfoFromServer,
)
return user
}

Expand All @@ -49,7 +53,7 @@ type User struct {
userSyncer *syncer.Syncer[*model_struct.LocalUser, syncer.NoResp, string]
commandSyncer *syncer.Syncer[*model_struct.LocalUserCommand, syncer.NoResp, string]
conversationCh chan common.Cmd2Value
UserCache *cache.Cache[string, *model_struct.LocalUser]
UserCache *cache.Manager[string, *model_struct.LocalUser]

//OnlineStatusCache *cache.Cache[string, *userPb.OnlineStatus]
}
Expand Down Expand Up @@ -174,37 +178,11 @@ func (u *User) updateSelfUserInfo(ctx context.Context, userInfo *sdkws.UserInfoW
return nil
}

func (u *User) GetUsersInfoWithCache(ctx context.Context, cacheKeys []string, fetchFunc func(ctx context.Context,
missingKeys []string) ([]*model_struct.LocalUser, error)) (usersInfo []*model_struct.LocalUser, err error) {
var missingKeys []string

for _, key := range cacheKeys {
if userInfo, ok := u.UserCache.Load(key); ok {
usersInfo = append(usersInfo, userInfo)
} else {
missingKeys = append(missingKeys, key)
}
}

if len(missingKeys) > 0 {
fetchedData, err := fetchFunc(ctx, missingKeys)
if err != nil {
return nil, err
}

for i, key := range missingKeys {
u.UserCache.Store(key, fetchedData[i])
}
for _, userInfo := range fetchedData {
usersInfo = append(usersInfo, userInfo)
u.UserCache.Store(userInfo.UserID, userInfo)
}
}

return usersInfo, nil
func (u *User) GetUserInfoWithCache(ctx context.Context, cacheKey string) (*model_struct.LocalUser, error) {
return u.UserCache.FetchGet(ctx, cacheKey)
}

func (u *User) GetUserInfoWithCache(ctx context.Context, cacheKey string, fetchFunc func(ctx context.Context, key string) (*model_struct.LocalUser, error)) (*model_struct.LocalUser, error) {
func (u *User) GetUserInfoWithCacheFunc(ctx context.Context, cacheKey string, fetchFunc func(ctx context.Context, key string) (*model_struct.LocalUser, error)) (*model_struct.LocalUser, error) {
if userInfo, ok := u.UserCache.Load(cacheKey); ok {
return userInfo, nil
}
Expand All @@ -217,3 +195,11 @@ func (u *User) GetUserInfoWithCache(ctx context.Context, cacheKey string, fetchF
u.UserCache.Store(cacheKey, fetchedData)
return fetchedData, nil
}

func (u *User) GetUsersInfoWithCache(ctx context.Context, cacheKeys []string) ([]*model_struct.LocalUser, error) {
m, err := u.UserCache.MultiFetchGet(ctx, cacheKeys)
if err != nil {
return nil, err
}
return datautil.MapToSlice(m), nil
}
8 changes: 4 additions & 4 deletions pkg/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ package cache

import "sync"

func NewCache[K comparable, V any]() *Cache[K, V] {
return &Cache[K, V]{}
}

// Cache is a Generic sync.Map structure.
type Cache[K comparable, V any] struct {
m sync.Map
}

func NewCache[K comparable, V any]() *Cache[K, V] {
return &Cache[K, V]{}
}

// Load returns the value stored in the map for a key, or nil if no value is present.
func (c *Cache[K, V]) Load(key K) (value V, ok bool) {
rawValue, ok := c.m.Load(key)
Expand Down
Loading

0 comments on commit 1f2f88e

Please sign in to comment.