Files
mostlymatter/store/localcachelayer/layer.go
2020-07-18 13:31:06 +05:30

393 строки
16 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package localcachelayer
import (
"time"
"github.com/mattermost/mattermost-server/v5/einterfaces"
"github.com/mattermost/mattermost-server/v5/model"
"github.com/mattermost/mattermost-server/v5/services/cache"
"github.com/mattermost/mattermost-server/v5/store"
)
const (
REACTION_CACHE_SIZE = 20000
REACTION_CACHE_SEC = 30 * 60
ROLE_CACHE_SIZE = 20000
ROLE_CACHE_SEC = 30 * 60
SCHEME_CACHE_SIZE = 20000
SCHEME_CACHE_SEC = 30 * 60
FILE_INFO_CACHE_SIZE = 25000
FILE_INFO_CACHE_SEC = 30 * 60
CHANNEL_GUEST_COUNT_CACHE_SIZE = model.CHANNEL_CACHE_SIZE
CHANNEL_GUEST_COUNT_CACHE_SEC = 30 * 60
WEBHOOK_CACHE_SIZE = 25000
WEBHOOK_CACHE_SEC = 15 * 60
EMOJI_CACHE_SIZE = 5000
EMOJI_CACHE_SEC = 30 * 60
CHANNEL_PINNEDPOSTS_COUNTS_CACHE_SIZE = model.CHANNEL_CACHE_SIZE
CHANNEL_PINNEDPOSTS_COUNTS_CACHE_SEC = 30 * 60
CHANNEL_MEMBERS_COUNTS_CACHE_SIZE = model.CHANNEL_CACHE_SIZE
CHANNEL_MEMBERS_COUNTS_CACHE_SEC = 30 * 60
LAST_POSTS_CACHE_SIZE = 20000
LAST_POSTS_CACHE_SEC = 30 * 60
TERMS_OF_SERVICE_CACHE_SIZE = 20000
TERMS_OF_SERVICE_CACHE_SEC = 30 * 60
LAST_POST_TIME_CACHE_SIZE = 25000
LAST_POST_TIME_CACHE_SEC = 15 * 60
USER_PROFILE_BY_ID_CACHE_SIZE = 20000
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_SEC = 30 * 60
CLEAR_CACHE_MESSAGE_DATA = ""
CHANNEL_CACHE_SEC = 15 * 60 // 15 mins
)
type LocalCacheStore struct {
store.Store
metrics einterfaces.MetricsInterface
cluster einterfaces.ClusterInterface
reaction LocalCacheReactionStore
reactionCache cache.Cache
fileInfo LocalCacheFileInfoStore
fileInfoCache cache.Cache
role LocalCacheRoleStore
roleCache cache.Cache
rolePermissionsCache cache.Cache
scheme LocalCacheSchemeStore
schemeCache cache.Cache
emoji LocalCacheEmojiStore
emojiCacheById cache.Cache
emojiIdCacheByName cache.Cache
channel LocalCacheChannelStore
channelMemberCountsCache cache.Cache
channelGuestCountCache cache.Cache
channelPinnedPostCountsCache cache.Cache
channelByIdCache cache.Cache
webhook LocalCacheWebhookStore
webhookCache cache.Cache
post LocalCachePostStore
postLastPostsCache cache.Cache
lastPostTimeCache cache.Cache
user LocalCacheUserStore
userProfileByIdsCache cache.Cache
profilesInChannelCache cache.Cache
team LocalCacheTeamStore
teamAllTeamIdsForUserCache cache.Cache
termsOfService LocalCacheTermsOfServiceStore
termsOfServiceCache cache.Cache
}
func NewLocalCacheLayer(baseStore store.Store, metrics einterfaces.MetricsInterface, cluster einterfaces.ClusterInterface, cacheProvider cache.Provider) LocalCacheStore {
localCacheStore := LocalCacheStore{
Store: baseStore,
cluster: cluster,
metrics: metrics,
}
// Reactions
localCacheStore.reactionCache = cacheProvider.NewCache(&cache.CacheOptions{
Size: REACTION_CACHE_SIZE,
Name: "Reaction",
DefaultExpiry: REACTION_CACHE_SEC * time.Second,
InvalidateClusterEvent: model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_REACTIONS,
})
localCacheStore.reaction = LocalCacheReactionStore{ReactionStore: baseStore.Reaction(), rootStore: &localCacheStore}
// Roles
localCacheStore.roleCache = cacheProvider.NewCache(&cache.CacheOptions{
Size: ROLE_CACHE_SIZE,
Name: "Role",
DefaultExpiry: ROLE_CACHE_SEC * time.Second,
InvalidateClusterEvent: model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_ROLES,
})
localCacheStore.rolePermissionsCache = cacheProvider.NewCache(&cache.CacheOptions{
Size: ROLE_CACHE_SIZE,
Name: "RolePermission",
DefaultExpiry: ROLE_CACHE_SEC * time.Second,
InvalidateClusterEvent: model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_ROLE_PERMISSIONS,
})
localCacheStore.role = LocalCacheRoleStore{RoleStore: baseStore.Role(), rootStore: &localCacheStore}
// Schemes
localCacheStore.schemeCache = cacheProvider.NewCache(&cache.CacheOptions{
Size: SCHEME_CACHE_SIZE,
Name: "Scheme",
DefaultExpiry: SCHEME_CACHE_SEC * time.Second,
InvalidateClusterEvent: model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_SCHEMES,
})
localCacheStore.scheme = LocalCacheSchemeStore{SchemeStore: baseStore.Scheme(), rootStore: &localCacheStore}
// FileInfo
localCacheStore.fileInfoCache = cacheProvider.NewCache(&cache.CacheOptions{
Size: FILE_INFO_CACHE_SIZE,
Name: "FileInfo",
DefaultExpiry: FILE_INFO_CACHE_SEC * time.Second,
InvalidateClusterEvent: model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_FILE_INFOS,
})
localCacheStore.fileInfo = LocalCacheFileInfoStore{FileInfoStore: baseStore.FileInfo(), rootStore: &localCacheStore}
// Webhooks
localCacheStore.webhookCache = cacheProvider.NewCache(&cache.CacheOptions{
Size: WEBHOOK_CACHE_SIZE,
Name: "Webhook",
DefaultExpiry: WEBHOOK_CACHE_SEC * time.Second,
InvalidateClusterEvent: model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_WEBHOOKS,
})
localCacheStore.webhook = LocalCacheWebhookStore{WebhookStore: baseStore.Webhook(), rootStore: &localCacheStore}
// Emojis
localCacheStore.emojiCacheById = cacheProvider.NewCache(&cache.CacheOptions{
Size: EMOJI_CACHE_SIZE,
Name: "EmojiById",
DefaultExpiry: EMOJI_CACHE_SEC * time.Second,
InvalidateClusterEvent: model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_EMOJIS_BY_ID,
})
localCacheStore.emojiIdCacheByName = cacheProvider.NewCache(&cache.CacheOptions{
Size: EMOJI_CACHE_SIZE,
Name: "EmojiByName",
DefaultExpiry: EMOJI_CACHE_SEC * time.Second,
InvalidateClusterEvent: model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_EMOJIS_ID_BY_NAME,
})
localCacheStore.emoji = LocalCacheEmojiStore{EmojiStore: baseStore.Emoji(), rootStore: &localCacheStore}
// Channels
localCacheStore.channelPinnedPostCountsCache = cacheProvider.NewCache(&cache.CacheOptions{
Size: CHANNEL_PINNEDPOSTS_COUNTS_CACHE_SIZE,
Name: "ChannelPinnedPostsCounts",
DefaultExpiry: CHANNEL_PINNEDPOSTS_COUNTS_CACHE_SEC * time.Second,
InvalidateClusterEvent: model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_PINNEDPOSTS_COUNTS,
})
localCacheStore.channelMemberCountsCache = cacheProvider.NewCache(&cache.CacheOptions{
Size: CHANNEL_MEMBERS_COUNTS_CACHE_SIZE,
Name: "ChannelMemberCounts",
DefaultExpiry: CHANNEL_MEMBERS_COUNTS_CACHE_SEC * time.Second,
InvalidateClusterEvent: model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_MEMBER_COUNTS,
})
localCacheStore.channelGuestCountCache = cacheProvider.NewCache(&cache.CacheOptions{
Size: CHANNEL_GUEST_COUNT_CACHE_SIZE,
Name: "ChannelGuestsCount",
DefaultExpiry: CHANNEL_GUEST_COUNT_CACHE_SEC * time.Second,
InvalidateClusterEvent: model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_GUEST_COUNT,
})
localCacheStore.channelByIdCache = cacheProvider.NewCache(&cache.CacheOptions{
Size: model.CHANNEL_CACHE_SIZE,
Name: "channelById",
DefaultExpiry: CHANNEL_CACHE_SEC * time.Second,
InvalidateClusterEvent: model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL,
})
localCacheStore.channel = LocalCacheChannelStore{ChannelStore: baseStore.Channel(), rootStore: &localCacheStore}
// Posts
localCacheStore.postLastPostsCache = cacheProvider.NewCache(&cache.CacheOptions{
Size: LAST_POSTS_CACHE_SIZE,
Name: "LastPost",
DefaultExpiry: LAST_POSTS_CACHE_SEC * time.Second,
InvalidateClusterEvent: model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_LAST_POSTS,
})
localCacheStore.lastPostTimeCache = cacheProvider.NewCache(&cache.CacheOptions{
Size: LAST_POST_TIME_CACHE_SIZE,
Name: "LastPostTime",
DefaultExpiry: LAST_POST_TIME_CACHE_SEC * time.Second,
InvalidateClusterEvent: model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_LAST_POST_TIME,
})
localCacheStore.post = LocalCachePostStore{PostStore: baseStore.Post(), rootStore: &localCacheStore}
// TOS
localCacheStore.termsOfServiceCache = cacheProvider.NewCache(&cache.CacheOptions{
Size: TERMS_OF_SERVICE_CACHE_SIZE,
Name: "TermsOfService",
DefaultExpiry: TERMS_OF_SERVICE_CACHE_SEC * time.Second,
InvalidateClusterEvent: model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_TERMS_OF_SERVICE,
})
localCacheStore.termsOfService = LocalCacheTermsOfServiceStore{TermsOfServiceStore: baseStore.TermsOfService(), rootStore: &localCacheStore}
// Users
localCacheStore.userProfileByIdsCache = cacheProvider.NewCache(&cache.CacheOptions{
Size: USER_PROFILE_BY_ID_CACHE_SIZE,
Name: "UserProfileByIds",
DefaultExpiry: USER_PROFILE_BY_ID_SEC * time.Second,
InvalidateClusterEvent: model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_PROFILE_BY_IDS,
})
localCacheStore.profilesInChannelCache = cacheProvider.NewCache(&cache.CacheOptions{
Size: PROFILES_IN_CHANNEL_CACHE_SIZE,
Name: "ProfilesInChannel",
DefaultExpiry: PROFILES_IN_CHANNEL_CACHE_SEC * time.Second,
InvalidateClusterEvent: model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_PROFILE_IN_CHANNEL,
})
localCacheStore.user = LocalCacheUserStore{UserStore: baseStore.User(), rootStore: &localCacheStore}
// Teams
localCacheStore.teamAllTeamIdsForUserCache = cacheProvider.NewCache(&cache.CacheOptions{
Size: TEAM_CACHE_SIZE,
Name: "Team",
DefaultExpiry: TEAM_CACHE_SEC * time.Second,
InvalidateClusterEvent: model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_TEAMS,
})
localCacheStore.team = LocalCacheTeamStore{TeamStore: baseStore.Team(), rootStore: &localCacheStore}
if cluster != nil {
cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_REACTIONS, localCacheStore.reaction.handleClusterInvalidateReaction)
cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_ROLES, localCacheStore.role.handleClusterInvalidateRole)
cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_ROLE_PERMISSIONS, localCacheStore.role.handleClusterInvalidateRolePermissions)
cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_SCHEMES, localCacheStore.scheme.handleClusterInvalidateScheme)
cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_FILE_INFOS, localCacheStore.fileInfo.handleClusterInvalidateFileInfo)
cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_LAST_POST_TIME, localCacheStore.post.handleClusterInvalidateLastPostTime)
cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_WEBHOOKS, localCacheStore.webhook.handleClusterInvalidateWebhook)
cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_EMOJIS_BY_ID, localCacheStore.emoji.handleClusterInvalidateEmojiById)
cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_EMOJIS_ID_BY_NAME, localCacheStore.emoji.handleClusterInvalidateEmojiIdByName)
cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_PINNEDPOSTS_COUNTS, localCacheStore.channel.handleClusterInvalidateChannelPinnedPostCount)
cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_MEMBER_COUNTS, localCacheStore.channel.handleClusterInvalidateChannelMemberCounts)
cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_GUEST_COUNT, localCacheStore.channel.handleClusterInvalidateChannelGuestCounts)
cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL, localCacheStore.channel.handleClusterInvalidateChannelById)
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_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)
}
return localCacheStore
}
func (s LocalCacheStore) Reaction() store.ReactionStore {
return s.reaction
}
func (s LocalCacheStore) Role() store.RoleStore {
return s.role
}
func (s LocalCacheStore) Scheme() store.SchemeStore {
return s.scheme
}
func (s LocalCacheStore) FileInfo() store.FileInfoStore {
return s.fileInfo
}
func (s LocalCacheStore) Webhook() store.WebhookStore {
return s.webhook
}
func (s LocalCacheStore) Emoji() store.EmojiStore {
return s.emoji
}
func (s LocalCacheStore) Channel() store.ChannelStore {
return s.channel
}
func (s LocalCacheStore) Post() store.PostStore {
return s.post
}
func (s LocalCacheStore) TermsOfService() store.TermsOfServiceStore {
return s.termsOfService
}
func (s LocalCacheStore) User() store.UserStore {
return s.user
}
func (s LocalCacheStore) Team() store.TeamStore {
return s.team
}
func (s LocalCacheStore) DropAllTables() {
s.Invalidate()
s.Store.DropAllTables()
}
func (s *LocalCacheStore) doInvalidateCacheCluster(cache cache.Cache, key string) {
cache.Remove(key)
if s.cluster != nil {
msg := &model.ClusterMessage{
Event: cache.GetInvalidateClusterEvent(),
SendType: model.CLUSTER_SEND_BEST_EFFORT,
Data: key,
}
s.cluster.SendClusterMessage(msg)
}
}
func (s *LocalCacheStore) doStandardAddToCache(cache cache.Cache, key string, value interface{}) {
cache.SetWithDefaultExpiry(key, value)
}
func (s *LocalCacheStore) doStandardReadCache(cache cache.Cache, key string, value interface{}) error {
if err := cache.Get(key, value); err == nil {
if s.metrics != nil {
s.metrics.IncrementMemCacheHitCounter(cache.Name())
}
return nil
} else {
if s.metrics != nil {
s.metrics.IncrementMemCacheMissCounter(cache.Name())
}
return err
}
}
func (s *LocalCacheStore) doClearCacheCluster(cache cache.Cache) {
cache.Purge()
if s.cluster != nil {
msg := &model.ClusterMessage{
Event: cache.GetInvalidateClusterEvent(),
SendType: model.CLUSTER_SEND_BEST_EFFORT,
Data: CLEAR_CACHE_MESSAGE_DATA,
}
s.cluster.SendClusterMessage(msg)
}
}
func (s *LocalCacheStore) Invalidate() {
s.doClearCacheCluster(s.reactionCache)
s.doClearCacheCluster(s.schemeCache)
s.doClearCacheCluster(s.roleCache)
s.doClearCacheCluster(s.fileInfoCache)
s.doClearCacheCluster(s.webhookCache)
s.doClearCacheCluster(s.emojiCacheById)
s.doClearCacheCluster(s.emojiIdCacheByName)
s.doClearCacheCluster(s.channelMemberCountsCache)
s.doClearCacheCluster(s.channelPinnedPostCountsCache)
s.doClearCacheCluster(s.channelGuestCountCache)
s.doClearCacheCluster(s.channelByIdCache)
s.doClearCacheCluster(s.postLastPostsCache)
s.doClearCacheCluster(s.termsOfServiceCache)
s.doClearCacheCluster(s.lastPostTimeCache)
s.doClearCacheCluster(s.userProfileByIdsCache)
s.doClearCacheCluster(s.profilesInChannelCache)
s.doClearCacheCluster(s.teamAllTeamIdsForUserCache)
s.doClearCacheCluster(s.rolePermissionsCache)
}