[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
@@ -56,35 +59,34 @@ const (
type LocalCacheStore struct { type LocalCacheStore struct {
store.Store store.Store
metrics einterfaces.MetricsInterface metrics einterfaces.MetricsInterface
cluster einterfaces.ClusterInterface cluster einterfaces.ClusterInterface
reaction LocalCacheReactionStore reaction LocalCacheReactionStore
reactionCache cache.Cache reactionCache cache.Cache
role LocalCacheRoleStore role LocalCacheRoleStore
roleCache cache.Cache roleCache cache.Cache
scheme LocalCacheSchemeStore scheme LocalCacheSchemeStore
schemeCache cache.Cache schemeCache cache.Cache
emoji LocalCacheEmojiStore emoji LocalCacheEmojiStore
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 postLastPostsCache cache.Cache
postLastPostsCache cache.Cache 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
termsOfServiceCache cache.Cache termsOfServiceCache cache.Cache
} }
func NewLocalCacheLayer(baseStore store.Store, metrics einterfaces.MetricsInterface, cluster einterfaces.ClusterInterface, cacheProvider cache.Provider) LocalCacheStore { func NewLocalCacheLayer(baseStore store.Store, metrics einterfaces.MetricsInterface, cluster einterfaces.ClusterInterface, cacheProvider cache.Provider) LocalCacheStore {
@@ -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
} }