mirror of
https://github.com/mattermost/mattermost.git
synced 2026-08-26 21:27:40 -05:00
Adding caching to get channel member (#5544)
This commit is contained in:
committed by
Joram Wilander
parent
3b8ed352d6
commit
75480bfdae
+6
-2
@@ -174,13 +174,15 @@ func UpdateUserToTeamAdmin(user *model.User, team *model.Team) {
|
||||
func MakeUserChannelAdmin(user *model.User, channel *model.Channel) {
|
||||
utils.DisableDebugLogForTest()
|
||||
|
||||
if cmr := <-Srv.Store.Channel().GetMember(channel.Id, user.Id); cmr.Err == nil {
|
||||
if cmr := <-Srv.Store.Channel().GetMember(channel.Id, user.Id, true); cmr.Err == nil {
|
||||
cm := cmr.Data.(model.ChannelMember)
|
||||
cm.Roles = "channel_admin channel_user"
|
||||
if sr := <-Srv.Store.Channel().UpdateMember(&cm); sr.Err != nil {
|
||||
utils.EnableDebugLogForTest()
|
||||
panic(sr.Err)
|
||||
}
|
||||
|
||||
InvalidateCacheForChannelMember(cm.ChannelId, cm.UserId)
|
||||
} else {
|
||||
utils.EnableDebugLogForTest()
|
||||
panic(cmr.Err)
|
||||
@@ -192,13 +194,15 @@ func MakeUserChannelAdmin(user *model.User, channel *model.Channel) {
|
||||
func MakeUserChannelUser(user *model.User, channel *model.Channel) {
|
||||
utils.DisableDebugLogForTest()
|
||||
|
||||
if cmr := <-Srv.Store.Channel().GetMember(channel.Id, user.Id); cmr.Err == nil {
|
||||
if cmr := <-Srv.Store.Channel().GetMember(channel.Id, user.Id, true); cmr.Err == nil {
|
||||
cm := cmr.Data.(model.ChannelMember)
|
||||
cm.Roles = "channel_user"
|
||||
if sr := <-Srv.Store.Channel().UpdateMember(&cm); sr.Err != nil {
|
||||
utils.EnableDebugLogForTest()
|
||||
panic(sr.Err)
|
||||
}
|
||||
|
||||
InvalidateCacheForChannelMember(cm.ChannelId, cm.UserId)
|
||||
} else {
|
||||
utils.EnableDebugLogForTest()
|
||||
panic(cmr.Err)
|
||||
|
||||
+13
-11
@@ -189,7 +189,7 @@ func WaitForChannelMembership(channelId string, userId string) {
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
result := <-Srv.Store.Channel().GetMember(channelId, userId)
|
||||
result := <-Srv.Store.Channel().GetMember(channelId, userId, true)
|
||||
|
||||
// If the membership was found then return
|
||||
if result.Err == nil {
|
||||
@@ -245,7 +245,7 @@ func updateChannel(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
sc := Srv.Store.Channel().Get(channel.Id, true)
|
||||
cmc := Srv.Store.Channel().GetMember(channel.Id, c.Session.UserId)
|
||||
cmc := Srv.Store.Channel().GetMember(channel.Id, c.Session.UserId, true)
|
||||
|
||||
if cresult := <-sc; cresult.Err != nil {
|
||||
c.Err = cresult.Err
|
||||
@@ -322,7 +322,7 @@ func updateChannelHeader(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
sc := Srv.Store.Channel().Get(channelId, true)
|
||||
cmc := Srv.Store.Channel().GetMember(channelId, c.Session.UserId)
|
||||
cmc := Srv.Store.Channel().GetMember(channelId, c.Session.UserId, true)
|
||||
|
||||
if cresult := <-sc; cresult.Err != nil {
|
||||
c.Err = cresult.Err
|
||||
@@ -431,7 +431,7 @@ func updateChannelPurpose(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
sc := Srv.Store.Channel().Get(channelId, true)
|
||||
cmc := Srv.Store.Channel().GetMember(channelId, c.Session.UserId)
|
||||
cmc := Srv.Store.Channel().GetMember(channelId, c.Session.UserId, true)
|
||||
|
||||
if cresult := <-sc; cresult.Err != nil {
|
||||
c.Err = cresult.Err
|
||||
@@ -588,7 +588,7 @@ func joinChannel(c *Context, channelChannel store.StoreChannel, userChannel stor
|
||||
channel := cresult.Data.(*model.Channel)
|
||||
user := uresult.Data.(*model.User)
|
||||
|
||||
if mresult := <-Srv.Store.Channel().GetMember(channel.Id, user.Id); mresult.Err == nil && mresult.Data != nil {
|
||||
if mresult := <-Srv.Store.Channel().GetMember(channel.Id, user.Id, true); mresult.Err == nil && mresult.Data != nil {
|
||||
// the user is already in the channel so just return successful
|
||||
return nil, channel
|
||||
}
|
||||
@@ -631,7 +631,7 @@ func AddUserToChannel(user *model.User, channel *model.Channel) (*model.ChannelM
|
||||
}
|
||||
|
||||
tmchan := Srv.Store.Team().GetMember(channel.TeamId, user.Id)
|
||||
cmchan := Srv.Store.Channel().GetMember(channel.Id, user.Id)
|
||||
cmchan := Srv.Store.Channel().GetMember(channel.Id, user.Id, true)
|
||||
|
||||
if result := <-tmchan; result.Err != nil {
|
||||
return nil, result.Err
|
||||
@@ -665,6 +665,7 @@ func AddUserToChannel(user *model.User, channel *model.Channel) (*model.ChannelM
|
||||
WaitForChannelMembership(channel.Id, user.Id)
|
||||
|
||||
InvalidateCacheForUser(user.Id)
|
||||
InvalidateCacheForChannelMember(channel.Id, user.Id)
|
||||
InvalidateCacheForChannelMembers(channel.Id)
|
||||
|
||||
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_ADDED, "", channel.Id, "", nil)
|
||||
@@ -801,7 +802,7 @@ func deleteChannel(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
id := params["channel_id"]
|
||||
|
||||
sc := Srv.Store.Channel().Get(id, true)
|
||||
scm := Srv.Store.Channel().GetMember(id, c.Session.UserId)
|
||||
scm := Srv.Store.Channel().GetMember(id, c.Session.UserId, true)
|
||||
cmc := Srv.Store.Channel().GetMemberCount(id, false)
|
||||
uc := Srv.Store.User().Get(c.Session.UserId)
|
||||
ihc := Srv.Store.Webhook().GetIncomingByChannel(id)
|
||||
@@ -905,7 +906,7 @@ func getChannel(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
id := params["channel_id"]
|
||||
|
||||
cchan := Srv.Store.Channel().Get(id, true)
|
||||
cmchan := Srv.Store.Channel().GetMember(id, c.Session.UserId)
|
||||
cmchan := Srv.Store.Channel().GetMember(id, c.Session.UserId, true)
|
||||
|
||||
if cresult := <-cchan; cresult.Err != nil {
|
||||
c.Err = cresult.Err
|
||||
@@ -1023,7 +1024,7 @@ func getChannelMember(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if result := <-Srv.Store.Channel().GetMember(channelId, userId); result.Err != nil {
|
||||
if result := <-Srv.Store.Channel().GetMember(channelId, userId, true); result.Err != nil {
|
||||
c.Err = result.Err
|
||||
return
|
||||
} else {
|
||||
@@ -1110,7 +1111,7 @@ func removeMember(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
sc := Srv.Store.Channel().Get(channelId, true)
|
||||
cmc := Srv.Store.Channel().GetMember(channelId, c.Session.UserId)
|
||||
cmc := Srv.Store.Channel().GetMember(channelId, c.Session.UserId, true)
|
||||
ouc := Srv.Store.User().Get(userIdToRemove)
|
||||
|
||||
if oresult := <-ouc; oresult.Err != nil {
|
||||
@@ -1202,7 +1203,7 @@ func updateNotifyProps(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
result := <-Srv.Store.Channel().GetMember(channelId, userId)
|
||||
result := <-Srv.Store.Channel().GetMember(channelId, userId, true)
|
||||
if result.Err != nil {
|
||||
c.Err = result.Err
|
||||
return
|
||||
@@ -1224,6 +1225,7 @@ func updateNotifyProps(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
} else {
|
||||
InvalidateCacheForUser(userId)
|
||||
InvalidateCacheForChannelMember(channelId, userId)
|
||||
|
||||
// return the updated notify properties including any unchanged ones
|
||||
w.Write([]byte(model.MapToJson(member.NotifyProps)))
|
||||
|
||||
@@ -191,6 +191,7 @@ func LeaveTeam(team *model.Team, user *model.User) *model.AppError {
|
||||
for _, channel := range *channelList {
|
||||
if channel.Type != model.CHANNEL_DIRECT {
|
||||
InvalidateCacheForChannelMembers(channel.Id)
|
||||
InvalidateCacheForChannelMember(channel.Id, user.Id)
|
||||
if result := <-Srv.Store.Channel().RemoveMember(channel.Id, user.Id); result.Err != nil {
|
||||
return result.Err
|
||||
}
|
||||
|
||||
@@ -158,6 +158,18 @@ func InvalidateCacheForUser(userId string) {
|
||||
}
|
||||
}
|
||||
|
||||
func InvalidateCacheForChannelMember(channelId string, userId string) {
|
||||
InvalidateCacheForChannelMemberSkipClusterSend(channelId, userId)
|
||||
|
||||
if einterfaces.GetClusterInterface() != nil {
|
||||
einterfaces.GetClusterInterface().InvalidateCacheForChannelMember(channelId, userId)
|
||||
}
|
||||
}
|
||||
|
||||
func InvalidateCacheForChannelMemberSkipClusterSend(channelId string, userId string) {
|
||||
Srv.Store.Channel().InvalidateMember(channelId, userId)
|
||||
}
|
||||
|
||||
func InvalidateCacheForUserSkipClusterSend(userId string) {
|
||||
Srv.Store.Channel().InvalidateAllChannelMembersForUser(userId)
|
||||
Srv.Store.User().InvalidateProfilesInChannelCacheByUser(userId)
|
||||
|
||||
@@ -19,6 +19,7 @@ type ClusterInterface interface {
|
||||
InvalidateCacheForChannelByName(teamId, name string)
|
||||
InvalidateCacheForChannelPosts(channelId string)
|
||||
InvalidateCacheForWebhook(webhookId string)
|
||||
InvalidateCacheForChannelMember(channelId string, userId string)
|
||||
Publish(event *model.WebSocketEvent)
|
||||
UpdateStatus(status *model.Status)
|
||||
GetLogs() ([]string, *model.AppError)
|
||||
|
||||
@@ -24,6 +24,12 @@ const (
|
||||
ALL_CHANNEL_MEMBERS_FOR_USER_CACHE_SIZE = model.SESSION_CACHE_SIZE
|
||||
ALL_CHANNEL_MEMBERS_FOR_USER_CACHE_SEC = 900 // 15 mins
|
||||
|
||||
ALL_CHANNEL_MEMBERS_NOTIFY_PROPS_FOR_CHANNEL_CACHE_SIZE = model.SESSION_CACHE_SIZE
|
||||
ALL_CHANNEL_MEMBERS_NOTIFY_PROPS_FOR_CHANNEL_CACHE_SEC = 1800 // 30 mins
|
||||
|
||||
CHANNEL_MEMBER_CACHE_SIZE = model.SESSION_CACHE_SIZE
|
||||
CHANNEL_MEMBER_CACHE_SEC = 900 // 15 mins
|
||||
|
||||
CHANNEL_MEMBERS_COUNTS_CACHE_SIZE = model.CHANNEL_CACHE_SIZE
|
||||
CHANNEL_MEMBERS_COUNTS_CACHE_SEC = 1800 // 30 mins
|
||||
|
||||
@@ -38,12 +44,14 @@ var channelMemberCountsCache = utils.NewLru(CHANNEL_MEMBERS_COUNTS_CACHE_SIZE)
|
||||
var allChannelMembersForUserCache = utils.NewLru(ALL_CHANNEL_MEMBERS_FOR_USER_CACHE_SIZE)
|
||||
var channelCache = utils.NewLru(model.CHANNEL_CACHE_SIZE)
|
||||
var channelByNameCache = utils.NewLru(model.CHANNEL_CACHE_SIZE)
|
||||
var channelMemberCache = utils.NewLru(CHANNEL_MEMBER_CACHE_SIZE)
|
||||
|
||||
func ClearChannelCaches() {
|
||||
channelMemberCountsCache.Purge()
|
||||
allChannelMembersForUserCache.Purge()
|
||||
channelCache.Purge()
|
||||
channelByNameCache.Purge()
|
||||
channelMemberCache.Purge()
|
||||
}
|
||||
|
||||
func NewSqlChannelStore(sqlStore *SqlStore) ChannelStore {
|
||||
@@ -710,11 +718,36 @@ func (s SqlChannelStore) GetMembers(channelId string) StoreChannel {
|
||||
return storeChannel
|
||||
}
|
||||
|
||||
func (s SqlChannelStore) GetMember(channelId string, userId string) StoreChannel {
|
||||
func (s SqlChannelStore) InvalidateMember(channelId string, userId string) {
|
||||
channelMemberCache.Remove(channelId + userId)
|
||||
}
|
||||
|
||||
func (s SqlChannelStore) GetMember(channelId string, userId string, allowFromCache bool) StoreChannel {
|
||||
storeChannel := make(StoreChannel, 1)
|
||||
|
||||
go func() {
|
||||
result := StoreResult{}
|
||||
metrics := einterfaces.GetMetricsInterface()
|
||||
|
||||
if allowFromCache {
|
||||
if cacheItem, ok := channelMemberCache.Get(channelId + userId); ok {
|
||||
if metrics != nil {
|
||||
metrics.IncrementMemCacheHitCounter("Channel Member")
|
||||
}
|
||||
result.Data = *cacheItem.(*model.ChannelMember)
|
||||
storeChannel <- result
|
||||
close(storeChannel)
|
||||
return
|
||||
} else {
|
||||
if metrics != nil {
|
||||
metrics.IncrementMemCacheMissCounter("Channel Member")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if metrics != nil {
|
||||
metrics.IncrementMemCacheMissCounter("Channel Member")
|
||||
}
|
||||
}
|
||||
|
||||
var member model.ChannelMember
|
||||
|
||||
@@ -726,6 +759,8 @@ func (s SqlChannelStore) GetMember(channelId string, userId string) StoreChannel
|
||||
}
|
||||
} else {
|
||||
result.Data = member
|
||||
|
||||
channelMemberCache.AddWithExpiresInSecs(channelId+userId, &member, CHANNEL_MEMBER_CACHE_SEC)
|
||||
}
|
||||
|
||||
storeChannel <- result
|
||||
|
||||
@@ -458,7 +458,7 @@ func TestChannelMemberStore(t *testing.T) {
|
||||
t.Fatal("Member update time incorrect on delete")
|
||||
}
|
||||
|
||||
member := (<-store.Channel().GetMember(o1.ChannelId, o1.UserId)).Data.(model.ChannelMember)
|
||||
member := (<-store.Channel().GetMember(o1.ChannelId, o1.UserId, false)).Data.(model.ChannelMember)
|
||||
if member.ChannelId != o1.ChannelId {
|
||||
t.Fatal("should have go member")
|
||||
}
|
||||
@@ -920,15 +920,15 @@ func TestGetMember(t *testing.T) {
|
||||
}
|
||||
Must(store.Channel().SaveMember(m2))
|
||||
|
||||
if result := <-store.Channel().GetMember(model.NewId(), userId); result.Err == nil {
|
||||
if result := <-store.Channel().GetMember(model.NewId(), userId, false); result.Err == nil {
|
||||
t.Fatal("should've failed to get member for non-existant channel")
|
||||
}
|
||||
|
||||
if result := <-store.Channel().GetMember(c1.Id, model.NewId()); result.Err == nil {
|
||||
if result := <-store.Channel().GetMember(c1.Id, model.NewId(), false); result.Err == nil {
|
||||
t.Fatal("should've failed to get member for non-existant user")
|
||||
}
|
||||
|
||||
if result := <-store.Channel().GetMember(c1.Id, userId); result.Err != nil {
|
||||
if result := <-store.Channel().GetMember(c1.Id, userId, false); result.Err != nil {
|
||||
t.Fatal("shouldn't have errored when getting member", result.Err)
|
||||
} else if member := result.Data.(model.ChannelMember); member.ChannelId != c1.Id {
|
||||
t.Fatal("should've gotten member of channel 1")
|
||||
@@ -936,7 +936,7 @@ func TestGetMember(t *testing.T) {
|
||||
t.Fatal("should've gotten member for user")
|
||||
}
|
||||
|
||||
if result := <-store.Channel().GetMember(c2.Id, userId); result.Err != nil {
|
||||
if result := <-store.Channel().GetMember(c2.Id, userId, false); result.Err != nil {
|
||||
t.Fatal("shouldn't have errored when getting member", result.Err)
|
||||
} else if member := result.Data.(model.ChannelMember); member.ChannelId != c2.Id {
|
||||
t.Fatal("should've gotten member of channel 2")
|
||||
|
||||
+2
-1
@@ -103,7 +103,8 @@ type ChannelStore interface {
|
||||
SaveMember(member *model.ChannelMember) StoreChannel
|
||||
UpdateMember(member *model.ChannelMember) StoreChannel
|
||||
GetMembers(channelId string) StoreChannel
|
||||
GetMember(channelId string, userId string) StoreChannel
|
||||
GetMember(channelId string, userId string, allowFromCache bool) StoreChannel
|
||||
InvalidateMember(channelId string, userId string)
|
||||
GetAllChannelMembersForUser(userId string, allowFromCache bool) StoreChannel
|
||||
InvalidateAllChannelMembersForUser(userId string)
|
||||
IsUserInChannelUseCache(userId string, channelId string) bool
|
||||
|
||||
Reference in New Issue
Block a user