[GH-13073] Migrate profilesInChannelCache cache from store/sqlstore/user_store.go to the new store/localcachelayer (#13536)

* Migrate profilesInChannelCache cache from store/sqlstore/user_store.go to the new store/localcachelayer

* Fix lint errors

* Remove unneeded cluster messages

* Remove unneeded cluster message registering

* Fix cluster messages

* Correct mistake with messages and restore model message
Этот коммит содержится в:
larkox
2020-01-11 11:52:44 -05:00
коммит произвёл Jesús Espino
родитель 605040c597
Коммит d4935fb22f
8 изменённых файлов: 255 добавлений и 106 удалений

Просмотреть файл

@@ -19,7 +19,6 @@ func (a *App) RegisterAllClusterMessageHandlers() {
a.Cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_UPDATE_STATUS, a.ClusterUpdateStatusHandler) a.Cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_UPDATE_STATUS, a.ClusterUpdateStatusHandler)
a.Cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_ALL_CACHES, a.ClusterInvalidateAllCachesHandler) a.Cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_ALL_CACHES, a.ClusterInvalidateAllCachesHandler)
a.Cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_MEMBERS_NOTIFY_PROPS, a.ClusterInvalidateCacheForChannelMembersNotifyPropHandler) a.Cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_MEMBERS_NOTIFY_PROPS, a.ClusterInvalidateCacheForChannelMembersNotifyPropHandler)
a.Cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_MEMBERS, a.ClusterInvalidateCacheForChannelMembersHandler)
a.Cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_BY_NAME, a.ClusterInvalidateCacheForChannelByNameHandler) a.Cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_BY_NAME, a.ClusterInvalidateCacheForChannelByNameHandler)
a.Cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_USER, a.ClusterInvalidateCacheForUserHandler) a.Cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_USER, a.ClusterInvalidateCacheForUserHandler)
a.Cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_USER_TEAMS, a.ClusterInvalidateCacheForUserTeamsHandler) a.Cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_USER_TEAMS, a.ClusterInvalidateCacheForUserTeamsHandler)
@@ -48,10 +47,6 @@ func (a *App) ClusterInvalidateCacheForChannelMembersNotifyPropHandler(msg *mode
a.InvalidateCacheForChannelMembersNotifyPropsSkipClusterSend(msg.Data) a.InvalidateCacheForChannelMembersNotifyPropsSkipClusterSend(msg.Data)
} }
func (a *App) ClusterInvalidateCacheForChannelMembersHandler(msg *model.ClusterMessage) {
a.InvalidateCacheForChannelMembersSkipClusterSend(msg.Data)
}
func (a *App) ClusterInvalidateCacheForChannelByNameHandler(msg *model.ClusterMessage) { func (a *App) ClusterInvalidateCacheForChannelByNameHandler(msg *model.ClusterMessage) {
a.InvalidateCacheForChannelByNameSkipClusterSend(msg.Props["id"], msg.Props["name"]) a.InvalidateCacheForChannelByNameSkipClusterSend(msg.Props["id"], msg.Props["name"])
} }

Просмотреть файл

@@ -224,22 +224,9 @@ func (a *App) InvalidateCacheForChannel(channel *model.Channel) {
} }
func (a *App) InvalidateCacheForChannelMembers(channelId string) { func (a *App) InvalidateCacheForChannelMembers(channelId string) {
a.InvalidateCacheForChannelMembersSkipClusterSend(channelId) a.Srv.Store.User().InvalidateProfilesInChannelCache(channelId)
a.Srv.Store.Channel().InvalidateMemberCount(channelId) a.Srv.Store.Channel().InvalidateMemberCount(channelId)
a.Srv.Store.Channel().InvalidateGuestCount(channelId) a.Srv.Store.Channel().InvalidateGuestCount(channelId)
if a.Cluster != nil {
msg := &model.ClusterMessage{
Event: model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_MEMBERS,
SendType: model.CLUSTER_SEND_BEST_EFFORT,
Data: channelId,
}
a.Cluster.SendClusterMessage(msg)
}
}
func (a *App) InvalidateCacheForChannelMembersSkipClusterSend(channelId string) {
a.Srv.Store.User().InvalidateProfilesInChannelCache(channelId)
} }
func (a *App) InvalidateCacheForChannelMembersNotifyProps(channelId string) { func (a *App) InvalidateCacheForChannelMembersNotifyProps(channelId string) {
@@ -275,6 +262,9 @@ func (a *App) InvalidateCacheForChannelPosts(channelId string) {
func (a *App) InvalidateCacheForUser(userId string) { func (a *App) InvalidateCacheForUser(userId string) {
a.InvalidateCacheForUserSkipClusterSend(userId) a.InvalidateCacheForUserSkipClusterSend(userId)
a.Srv.Store.User().InvalidateProfilesInChannelCacheByUser(userId)
a.Srv.Store.User().InvalidateProfileCacheForUser(userId)
if a.Cluster != nil { if a.Cluster != nil {
msg := &model.ClusterMessage{ msg := &model.ClusterMessage{
Event: model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_USER, Event: model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_USER,
@@ -301,8 +291,6 @@ func (a *App) InvalidateCacheForUserTeams(userId string) {
func (a *App) InvalidateCacheForUserSkipClusterSend(userId string) { func (a *App) InvalidateCacheForUserSkipClusterSend(userId string) {
a.Srv.Store.Channel().InvalidateAllChannelMembersForUser(userId) a.Srv.Store.Channel().InvalidateAllChannelMembersForUser(userId)
a.Srv.Store.User().InvalidateProfilesInChannelCacheByUser(userId)
a.Srv.Store.User().InvalidateProfileCacheForUser(userId)
hub := a.GetHubForUserId(userId) hub := a.GetHubForUserId(userId)
if hub != nil { if hub != nil {

Просмотреть файл

@@ -25,6 +25,7 @@ const (
CLUSTER_EVENT_CLEAR_SESSION_CACHE_FOR_USER = "clear_session_user" CLUSTER_EVENT_CLEAR_SESSION_CACHE_FOR_USER = "clear_session_user"
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_ROLES = "inv_roles" CLUSTER_EVENT_INVALIDATE_CACHE_FOR_ROLES = "inv_roles"
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_PROFILE_BY_IDS = "inv_profile_ids" CLUSTER_EVENT_INVALIDATE_CACHE_FOR_PROFILE_BY_IDS = "inv_profile_ids"
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_PROFILE_IN_CHANNEL = "inv_profile_in_channel"
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_SCHEMES = "inv_schemes" CLUSTER_EVENT_INVALIDATE_CACHE_FOR_SCHEMES = "inv_schemes"
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_WEBHOOKS = "inv_webhooks" CLUSTER_EVENT_INVALIDATE_CACHE_FOR_WEBHOOKS = "inv_webhooks"
CLUSTER_EVENT_INVALIDATE_CACHE_FOR_EMOJIS_BY_ID = "inv_emojis_by_id" CLUSTER_EVENT_INVALIDATE_CACHE_FOR_EMOJIS_BY_ID = "inv_emojis_by_id"

Просмотреть файл

@@ -46,6 +46,9 @@ const (
USER_PROFILE_BY_ID_CACHE_SIZE = 20000 USER_PROFILE_BY_ID_CACHE_SIZE = 20000
USER_PROFILE_BY_ID_SEC = 30 * 60 USER_PROFILE_BY_ID_SEC = 30 * 60
PROFILES_IN_CHANNEL_CACHE_SIZE = model.CHANNEL_CACHE_SIZE
PROFILES_IN_CHANNEL_CACHE_SEC = 15 * 60
TEAM_CACHE_SIZE = 20000 TEAM_CACHE_SIZE = 20000
TEAM_CACHE_SEC = 30 * 60 TEAM_CACHE_SEC = 30 * 60
@@ -68,12 +71,10 @@ type LocalCacheStore struct {
emojiCacheById cache.Cache emojiCacheById cache.Cache
emojiIdCacheByName cache.Cache emojiIdCacheByName cache.Cache
channel LocalCacheChannelStore channel LocalCacheChannelStore
channelMemberCountsCache cache.Cache channelMemberCountsCache cache.Cache
channelGuestCountCache cache.Cache channelGuestCountCache cache.Cache
channelPinnedPostCountsCache cache.Cache channelPinnedPostCountsCache cache.Cache
channelByIdCache cache.Cache channelByIdCache cache.Cache
webhook LocalCacheWebhookStore webhook LocalCacheWebhookStore
webhookCache cache.Cache webhookCache cache.Cache
post LocalCachePostStore post LocalCachePostStore
@@ -81,6 +82,7 @@ type LocalCacheStore struct {
lastPostTimeCache cache.Cache lastPostTimeCache cache.Cache
user LocalCacheUserStore user LocalCacheUserStore
userProfileByIdsCache cache.Cache userProfileByIdsCache cache.Cache
profilesInChannelCache cache.Cache
team LocalCacheTeamStore team LocalCacheTeamStore
teamAllTeamIdsForUserCache cache.Cache teamAllTeamIdsForUserCache cache.Cache
termsOfService LocalCacheTermsOfServiceStore termsOfService LocalCacheTermsOfServiceStore
@@ -121,7 +123,7 @@ func NewLocalCacheLayer(baseStore store.Store, metrics einterfaces.MetricsInterf
localCacheStore.termsOfServiceCache = cacheProvider.NewCacheWithParams(TERMS_OF_SERVICE_CACHE_SIZE, "TermsOfService", TERMS_OF_SERVICE_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_TERMS_OF_SERVICE) localCacheStore.termsOfServiceCache = cacheProvider.NewCacheWithParams(TERMS_OF_SERVICE_CACHE_SIZE, "TermsOfService", TERMS_OF_SERVICE_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_TERMS_OF_SERVICE)
localCacheStore.termsOfService = LocalCacheTermsOfServiceStore{TermsOfServiceStore: baseStore.TermsOfService(), rootStore: &localCacheStore} localCacheStore.termsOfService = LocalCacheTermsOfServiceStore{TermsOfServiceStore: baseStore.TermsOfService(), rootStore: &localCacheStore}
localCacheStore.userProfileByIdsCache = cacheProvider.NewCacheWithParams(USER_PROFILE_BY_ID_CACHE_SIZE, "UserProfileByIds", USER_PROFILE_BY_ID_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_PROFILE_BY_IDS) localCacheStore.userProfileByIdsCache = cacheProvider.NewCacheWithParams(USER_PROFILE_BY_ID_CACHE_SIZE, "UserProfileByIds", USER_PROFILE_BY_ID_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_PROFILE_BY_IDS)
localCacheStore.profilesInChannelCache = cacheProvider.NewCacheWithParams(PROFILES_IN_CHANNEL_CACHE_SIZE, "ProfilesInChannel", PROFILES_IN_CHANNEL_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_PROFILE_IN_CHANNEL)
localCacheStore.user = LocalCacheUserStore{UserStore: baseStore.User(), rootStore: &localCacheStore} localCacheStore.user = LocalCacheUserStore{UserStore: baseStore.User(), rootStore: &localCacheStore}
localCacheStore.teamAllTeamIdsForUserCache = cacheProvider.NewCacheWithParams(TEAM_CACHE_SIZE, "Team", TEAM_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_TEAMS) localCacheStore.teamAllTeamIdsForUserCache = cacheProvider.NewCacheWithParams(TEAM_CACHE_SIZE, "Team", TEAM_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_TEAMS)
localCacheStore.team = LocalCacheTeamStore{TeamStore: baseStore.Team(), rootStore: &localCacheStore} localCacheStore.team = LocalCacheTeamStore{TeamStore: baseStore.Team(), rootStore: &localCacheStore}
@@ -141,6 +143,7 @@ func NewLocalCacheLayer(baseStore store.Store, metrics einterfaces.MetricsInterf
cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_LAST_POSTS, localCacheStore.post.handleClusterInvalidateLastPosts) cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_LAST_POSTS, localCacheStore.post.handleClusterInvalidateLastPosts)
cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_TERMS_OF_SERVICE, localCacheStore.termsOfService.handleClusterInvalidateTermsOfService) cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_TERMS_OF_SERVICE, localCacheStore.termsOfService.handleClusterInvalidateTermsOfService)
cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_PROFILE_BY_IDS, localCacheStore.user.handleClusterInvalidateScheme) cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_PROFILE_BY_IDS, localCacheStore.user.handleClusterInvalidateScheme)
cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_PROFILE_IN_CHANNEL, localCacheStore.user.handleClusterInvalidateProfilesInChannel)
cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_TEAMS, localCacheStore.team.handleClusterInvalidateTeam) cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_TEAMS, localCacheStore.team.handleClusterInvalidateTeam)
} }
return localCacheStore return localCacheStore
@@ -247,5 +250,6 @@ func (s *LocalCacheStore) Invalidate() {
s.doClearCacheCluster(s.termsOfServiceCache) s.doClearCacheCluster(s.termsOfServiceCache)
s.doClearCacheCluster(s.lastPostTimeCache) s.doClearCacheCluster(s.lastPostTimeCache)
s.doClearCacheCluster(s.userProfileByIdsCache) s.doClearCacheCluster(s.userProfileByIdsCache)
s.doClearCacheCluster(s.profilesInChannelCache)
s.doClearCacheCluster(s.teamAllTeamIdsForUserCache) s.doClearCacheCluster(s.teamAllTeamIdsForUserCache)
} }

Просмотреть файл

@@ -20,13 +20,101 @@ var mainHelper *testlib.MainHelper
func getMockCacheProvider() *mocks.CacheProvider { func getMockCacheProvider() *mocks.CacheProvider {
mockCacheProvider := mocks.CacheProvider{} mockCacheProvider := mocks.CacheProvider{}
//todo: replace this line with mocks for all tests //todo: replace this line with mocks for all tests
mockCache := lru.New(128) mockCacheProvider.On("NewCacheWithParams",
mock.AnythingOfType("int"),
"Reaction",
mock.AnythingOfType("int64"),
mock.AnythingOfType("string")).Return(lru.New(128))
mockCacheProvider.On("NewCacheWithParams", mockCacheProvider.On("NewCacheWithParams",
mock.AnythingOfType("int"), mock.AnythingOfType("int"),
mock.AnythingOfType("string"), "Role",
mock.AnythingOfType("int64"), mock.AnythingOfType("int64"),
mock.AnythingOfType("string")).Return(mockCache) mock.AnythingOfType("string")).Return(lru.New(128))
mockCacheProvider.On("NewCacheWithParams",
mock.AnythingOfType("int"),
"Scheme",
mock.AnythingOfType("int64"),
mock.AnythingOfType("string")).Return(lru.New(128))
mockCacheProvider.On("NewCacheWithParams",
mock.AnythingOfType("int"),
"Webhook",
mock.AnythingOfType("int64"),
mock.AnythingOfType("string")).Return(lru.New(128))
mockCacheProvider.On("NewCacheWithParams",
mock.AnythingOfType("int"),
"EmojiById",
mock.AnythingOfType("int64"),
mock.AnythingOfType("string")).Return(lru.New(128))
mockCacheProvider.On("NewCacheWithParams",
mock.AnythingOfType("int"),
"EmojiByName",
mock.AnythingOfType("int64"),
mock.AnythingOfType("string")).Return(lru.New(128))
mockCacheProvider.On("NewCacheWithParams",
mock.AnythingOfType("int"),
"ChannelPinnedPostsCounts",
mock.AnythingOfType("int64"),
mock.AnythingOfType("string")).Return(lru.New(128))
mockCacheProvider.On("NewCacheWithParams",
mock.AnythingOfType("int"),
"ChannelMemberCounts",
mock.AnythingOfType("int64"),
mock.AnythingOfType("string")).Return(lru.New(128))
mockCacheProvider.On("NewCacheWithParams",
mock.AnythingOfType("int"),
"ChannelGuestsCount",
mock.AnythingOfType("int64"),
mock.AnythingOfType("string")).Return(lru.New(128))
mockCacheProvider.On("NewCacheWithParams",
mock.AnythingOfType("int"),
"channelById",
mock.AnythingOfType("int64"),
mock.AnythingOfType("string")).Return(lru.New(128))
mockCacheProvider.On("NewCacheWithParams",
mock.AnythingOfType("int"),
"LastPost",
mock.AnythingOfType("int64"),
mock.AnythingOfType("string")).Return(lru.New(128))
mockCacheProvider.On("NewCacheWithParams",
mock.AnythingOfType("int"),
"LastPostTime",
mock.AnythingOfType("int64"),
mock.AnythingOfType("string")).Return(lru.New(128))
mockCacheProvider.On("NewCacheWithParams",
mock.AnythingOfType("int"),
"TermsOfService",
mock.AnythingOfType("int64"),
mock.AnythingOfType("string")).Return(lru.New(128))
mockCacheProvider.On("NewCacheWithParams",
mock.AnythingOfType("int"),
"UserProfileByIds",
mock.AnythingOfType("int64"),
mock.AnythingOfType("string")).Return(lru.New(128))
mockCacheProvider.On("NewCacheWithParams",
mock.AnythingOfType("int"),
"ProfilesInChannel",
mock.AnythingOfType("int64"),
mock.AnythingOfType("string")).Return(lru.New(128))
mockCacheProvider.On("NewCacheWithParams",
mock.AnythingOfType("int"),
"Team",
mock.AnythingOfType("int64"),
mock.AnythingOfType("string")).Return(lru.New(128))
return &mockCacheProvider return &mockCacheProvider
} }
@@ -128,6 +216,13 @@ func getMockStore() *mocks.Store {
mockUserStore := mocks.UserStore{} mockUserStore := mocks.UserStore{}
mockUserStore.On("GetProfileByIds", []string{"123"}, &store.UserGetByIdsOpts{}, true).Return(fakeUser, nil) mockUserStore.On("GetProfileByIds", []string{"123"}, &store.UserGetByIdsOpts{}, true).Return(fakeUser, nil)
mockUserStore.On("GetProfileByIds", []string{"123"}, &store.UserGetByIdsOpts{}, false).Return(fakeUser, nil) mockUserStore.On("GetProfileByIds", []string{"123"}, &store.UserGetByIdsOpts{}, false).Return(fakeUser, nil)
fakeProfilesInChannelMap := map[string]*model.User{
"456": {Id: "456"},
}
mockUserStore.On("GetAllProfilesInChannel", "123", true).Return(fakeProfilesInChannelMap, nil)
mockUserStore.On("GetAllProfilesInChannel", "123", false).Return(fakeProfilesInChannelMap, nil)
mockUserStore.On("Get", "123").Return(fakeUser[0], nil) mockUserStore.On("Get", "123").Return(fakeUser[0], nil)
mockStore.On("User").Return(&mockUserStore) mockStore.On("User").Return(&mockUserStore)

Просмотреть файл

@@ -23,11 +23,21 @@ func (s *LocalCacheUserStore) handleClusterInvalidateScheme(msg *model.ClusterMe
} }
} }
func (s *LocalCacheUserStore) handleClusterInvalidateProfilesInChannel(msg *model.ClusterMessage) {
if msg.Data == CLEAR_CACHE_MESSAGE_DATA {
s.rootStore.profilesInChannelCache.Purge()
} else {
s.rootStore.profilesInChannelCache.Remove(msg.Data)
}
}
func (s LocalCacheUserStore) ClearCaches() { func (s LocalCacheUserStore) ClearCaches() {
s.rootStore.userProfileByIdsCache.Purge() s.rootStore.userProfileByIdsCache.Purge()
s.rootStore.profilesInChannelCache.Purge()
if s.rootStore.metrics != nil { if s.rootStore.metrics != nil {
s.rootStore.metrics.IncrementMemCacheInvalidationCounter("Profile By Ids - Purge") s.rootStore.metrics.IncrementMemCacheInvalidationCounter("Profile By Ids - Purge")
s.rootStore.metrics.IncrementMemCacheInvalidationCounter("Profiles in Channel - Purge")
} }
} }
@@ -39,6 +49,48 @@ func (s LocalCacheUserStore) InvalidateProfileCacheForUser(userId string) {
} }
} }
func (s LocalCacheUserStore) InvalidateProfilesInChannelCacheByUser(userId string) {
keys := s.rootStore.profilesInChannelCache.Keys()
for _, key := range keys {
if cacheItem, ok := s.rootStore.profilesInChannelCache.Get(key); ok {
userMap := cacheItem.(map[string]*model.User)
if _, userInCache := userMap[userId]; userInCache {
s.rootStore.doInvalidateCacheCluster(s.rootStore.profilesInChannelCache, key.(string))
if s.rootStore.metrics != nil {
s.rootStore.metrics.IncrementMemCacheInvalidationCounter("Profiles in Channel - Remove by User")
}
}
}
}
}
func (s LocalCacheUserStore) InvalidateProfilesInChannelCache(channelId string) {
s.rootStore.doInvalidateCacheCluster(s.rootStore.profilesInChannelCache, channelId)
if s.rootStore.metrics != nil {
s.rootStore.metrics.IncrementMemCacheInvalidationCounter("Profiles in Channel - Remove by Channel")
}
}
func (s LocalCacheUserStore) GetAllProfilesInChannel(channelId string, allowFromCache bool) (map[string]*model.User, *model.AppError) {
if allowFromCache {
if cacheItem := s.rootStore.doStandardReadCache(s.rootStore.profilesInChannelCache, channelId); cacheItem != nil {
return cacheItem.(map[string]*model.User), nil
}
}
userMap, err := s.UserStore.GetAllProfilesInChannel(channelId, allowFromCache)
if err != nil {
return nil, err
}
if allowFromCache {
s.rootStore.doStandardAddToCache(s.rootStore.profilesInChannelCache, channelId, userMap)
}
return userMap, nil
}
func (s LocalCacheUserStore) GetProfileByIds(userIds []string, options *store.UserGetByIdsOpts, allowFromCache bool) ([]*model.User, *model.AppError) { func (s LocalCacheUserStore) GetProfileByIds(userIds []string, options *store.UserGetByIdsOpts, allowFromCache bool) ([]*model.User, *model.AppError) {
if !allowFromCache { if !allowFromCache {
return s.UserStore.GetProfileByIds(userIds, options, false) return s.UserStore.GetProfileByIds(userIds, options, false)

Просмотреть файл

@@ -68,10 +68,76 @@ func TestUserStoreGetProfileByIdsCache(t *testing.T) {
}) })
} }
func TestUserStoreProfilesInChannelCache(t *testing.T) {
fakeChannelId := "123"
fakeUserId := "456"
fakeMap := map[string]*model.User{
fakeUserId: {Id: "456"},
}
t.Run("first call not cached, second cached and returning same data", func(t *testing.T) {
mockStore := getMockStore()
mockCacheProvider := getMockCacheProvider()
cachedStore := NewLocalCacheLayer(mockStore, nil, nil, mockCacheProvider)
gotMap, err := cachedStore.User().GetAllProfilesInChannel(fakeChannelId, true)
require.Nil(t, err)
assert.Equal(t, fakeMap, gotMap)
mockStore.User().(*mocks.UserStore).AssertNumberOfCalls(t, "GetAllProfilesInChannel", 1)
_, _ = cachedStore.User().GetAllProfilesInChannel(fakeChannelId, true)
mockStore.User().(*mocks.UserStore).AssertNumberOfCalls(t, "GetAllProfilesInChannel", 1)
})
t.Run("first call not cached, second force not cached", func(t *testing.T) {
mockStore := getMockStore()
mockCacheProvider := getMockCacheProvider()
cachedStore := NewLocalCacheLayer(mockStore, nil, nil, mockCacheProvider)
gotMap, err := cachedStore.User().GetAllProfilesInChannel(fakeChannelId, true)
require.Nil(t, err)
assert.Equal(t, fakeMap, gotMap)
mockStore.User().(*mocks.UserStore).AssertNumberOfCalls(t, "GetAllProfilesInChannel", 1)
_, _ = cachedStore.User().GetAllProfilesInChannel(fakeChannelId, false)
mockStore.User().(*mocks.UserStore).AssertNumberOfCalls(t, "GetAllProfilesInChannel", 2)
})
t.Run("first call not cached, invalidate by channel, and then not cached again", func(t *testing.T) {
mockStore := getMockStore()
mockCacheProvider := getMockCacheProvider()
cachedStore := NewLocalCacheLayer(mockStore, nil, nil, mockCacheProvider)
gotMap, err := cachedStore.User().GetAllProfilesInChannel(fakeChannelId, true)
require.Nil(t, err)
assert.Equal(t, fakeMap, gotMap)
mockStore.User().(*mocks.UserStore).AssertNumberOfCalls(t, "GetAllProfilesInChannel", 1)
cachedStore.User().InvalidateProfilesInChannelCache("123")
_, _ = cachedStore.User().GetAllProfilesInChannel(fakeChannelId, true)
mockStore.User().(*mocks.UserStore).AssertNumberOfCalls(t, "GetAllProfilesInChannel", 2)
})
t.Run("first call not cached, invalidate by user, and then not cached again", func(t *testing.T) {
mockStore := getMockStore()
mockCacheProvider := getMockCacheProvider()
cachedStore := NewLocalCacheLayer(mockStore, nil, nil, mockCacheProvider)
gotMap, err := cachedStore.User().GetAllProfilesInChannel(fakeChannelId, true)
require.Nil(t, err)
assert.Equal(t, fakeMap, gotMap)
mockStore.User().(*mocks.UserStore).AssertNumberOfCalls(t, "GetAllProfilesInChannel", 1)
cachedStore.User().InvalidateProfilesInChannelCacheByUser("456")
_, _ = cachedStore.User().GetAllProfilesInChannel(fakeChannelId, true)
mockStore.User().(*mocks.UserStore).AssertNumberOfCalls(t, "GetAllProfilesInChannel", 2)
})
}
func TestUserStoreGetCache(t *testing.T) { func TestUserStoreGetCache(t *testing.T) {
fakeUserId := "123" fakeUserId := "123"
fakeUser := &model.User{Id: "123"} fakeUser := &model.User{Id: "123"}
t.Run("first call not cached, second cached and returning same data", func(t *testing.T) { t.Run("first call not cached, second cached and returning same data", func(t *testing.T) {
mockStore := getMockStore() mockStore := getMockStore()
mockCacheProvider := getMockCacheProvider() mockCacheProvider := getMockCacheProvider()

Просмотреть файл

@@ -16,14 +16,10 @@ import (
"github.com/mattermost/mattermost-server/v5/einterfaces" "github.com/mattermost/mattermost-server/v5/einterfaces"
"github.com/mattermost/mattermost-server/v5/model" "github.com/mattermost/mattermost-server/v5/model"
"github.com/mattermost/mattermost-server/v5/services/cache"
"github.com/mattermost/mattermost-server/v5/services/cache/lru"
"github.com/mattermost/mattermost-server/v5/store" "github.com/mattermost/mattermost-server/v5/store"
) )
const ( const (
PROFILES_IN_CHANNEL_CACHE_SIZE = model.CHANNEL_CACHE_SIZE
PROFILES_IN_CHANNEL_CACHE_SEC = 900 // 15 mins
MAX_GROUP_CHANNELS_FOR_PROFILES = 50 MAX_GROUP_CHANNELS_FOR_PROFILES = 50
) )
@@ -42,15 +38,7 @@ type SqlUserStore struct {
usersQuery sq.SelectBuilder usersQuery sq.SelectBuilder
} }
var profilesInChannelCache cache.Cache = lru.New(PROFILES_IN_CHANNEL_CACHE_SIZE) func (us SqlUserStore) ClearCaches() {}
func (us SqlUserStore) ClearCaches() {
profilesInChannelCache.Purge()
if us.metrics != nil {
us.metrics.IncrementMemCacheInvalidationCounter("Profiles in Channel - Purge")
}
}
func (us SqlUserStore) InvalidateProfileCacheForUser(userId string) {} func (us SqlUserStore) InvalidateProfileCacheForUser(userId string) {}
@@ -532,28 +520,9 @@ func (us SqlUserStore) GetProfiles(options *model.UserGetOptions) ([]*model.User
return users, nil return users, nil
} }
func (us SqlUserStore) InvalidateProfilesInChannelCacheByUser(userId string) { func (us SqlUserStore) InvalidateProfilesInChannelCacheByUser(userId string) {}
keys := profilesInChannelCache.Keys()
for _, key := range keys { func (us SqlUserStore) InvalidateProfilesInChannelCache(channelId string) {}
if cacheItem, ok := profilesInChannelCache.Get(key); ok {
userMap := cacheItem.(map[string]*model.User)
if _, userInCache := userMap[userId]; userInCache {
profilesInChannelCache.Remove(key)
if us.metrics != nil {
us.metrics.IncrementMemCacheInvalidationCounter("Profiles in Channel - Remove by User")
}
}
}
}
}
func (us SqlUserStore) InvalidateProfilesInChannelCache(channelId string) {
profilesInChannelCache.Remove(channelId)
if us.metrics != nil {
us.metrics.IncrementMemCacheInvalidationCounter("Profiles in Channel - Remove by Channel")
}
}
func (us SqlUserStore) GetProfilesInChannel(channelId string, offset int, limit int) ([]*model.User, *model.AppError) { func (us SqlUserStore) GetProfilesInChannel(channelId string, offset int, limit int) ([]*model.User, *model.AppError) {
query := us.usersQuery. query := us.usersQuery.
@@ -613,23 +582,6 @@ func (us SqlUserStore) GetProfilesInChannelByStatus(channelId string, offset int
} }
func (us SqlUserStore) GetAllProfilesInChannel(channelId string, allowFromCache bool) (map[string]*model.User, *model.AppError) { func (us SqlUserStore) GetAllProfilesInChannel(channelId string, allowFromCache bool) (map[string]*model.User, *model.AppError) {
if allowFromCache {
if cacheItem, ok := profilesInChannelCache.Get(channelId); ok {
if us.metrics != nil {
us.metrics.IncrementMemCacheHitCounter("Profiles in Channel")
}
return cacheItem.(map[string]*model.User), nil
} else {
if us.metrics != nil {
us.metrics.IncrementMemCacheMissCounter("Profiles in Channel")
}
}
} else {
if us.metrics != nil {
us.metrics.IncrementMemCacheMissCounter("Profiles in Channel")
}
}
query := us.usersQuery. query := us.usersQuery.
Join("ChannelMembers cm ON ( cm.UserId = u.Id )"). Join("ChannelMembers cm ON ( cm.UserId = u.Id )").
Where("cm.ChannelId = ?", channelId). Where("cm.ChannelId = ?", channelId).
@@ -653,10 +605,6 @@ func (us SqlUserStore) GetAllProfilesInChannel(channelId string, allowFromCache
userMap[u.Id] = u userMap[u.Id] = u
} }
if allowFromCache {
profilesInChannelCache.AddWithExpiresInSecs(channelId, userMap, PROFILES_IN_CHANNEL_CACHE_SEC)
}
return userMap, nil return userMap, nil
} }