github.com/vnforks/kid/v5@v5.22.1-0.20200408055009-b89d99c65676/store/localcachelayer/layer.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package localcachelayer 5 6 import ( 7 "github.com/vnforks/kid/v5/einterfaces" 8 "github.com/vnforks/kid/v5/model" 9 "github.com/vnforks/kid/v5/services/cache" 10 "github.com/vnforks/kid/v5/store" 11 ) 12 13 const ( 14 REACTION_CACHE_SIZE = 20000 15 REACTION_CACHE_SEC = 30 * 60 16 17 ROLE_CACHE_SIZE = 20000 18 ROLE_CACHE_SEC = 30 * 60 19 20 SCHEME_CACHE_SIZE = 20000 21 SCHEME_CACHE_SEC = 30 * 60 22 23 FILE_INFO_CACHE_SIZE = 25000 24 FILE_INFO_CACHE_SEC = 30 * 60 25 26 CLASS_GUEST_COUNT_CACHE_SIZE = model.CLASS_CACHE_SIZE 27 CLASS_GUEST_COUNT_CACHE_SEC = 30 * 60 28 29 WEBHOOK_CACHE_SIZE = 25000 30 WEBHOOK_CACHE_SEC = 15 * 60 31 32 EMOJI_CACHE_SIZE = 5000 33 EMOJI_CACHE_SEC = 30 * 60 34 35 CLASS_PINNEDPOSTS_COUNTS_CACHE_SIZE = model.CLASS_CACHE_SIZE 36 CLASS_PINNEDPOSTS_COUNTS_CACHE_SEC = 30 * 60 37 38 CLASS_MEMBERS_COUNTS_CACHE_SIZE = model.CLASS_CACHE_SIZE 39 CLASS_MEMBERS_COUNTS_CACHE_SEC = 30 * 60 40 41 LAST_POSTS_CACHE_SIZE = 20000 42 LAST_POSTS_CACHE_SEC = 30 * 60 43 44 TERMS_OF_SERVICE_CACHE_SIZE = 20000 45 TERMS_OF_SERVICE_CACHE_SEC = 30 * 60 46 LAST_POST_TIME_CACHE_SIZE = 25000 47 LAST_POST_TIME_CACHE_SEC = 15 * 60 48 49 USER_PROFILE_BY_ID_CACHE_SIZE = 20000 50 USER_PROFILE_BY_ID_SEC = 30 * 60 51 52 PROFILES_IN_CLASS_CACHE_SIZE = model.CLASS_CACHE_SIZE 53 PROFILES_IN_CLASS_CACHE_SEC = 15 * 60 54 55 BRANCH_CACHE_SIZE = 20000 56 BRANCH_CACHE_SEC = 30 * 60 57 58 CLEAR_CACHE_MESSAGE_DATA = "" 59 60 CLASS_CACHE_SEC = 15 * 60 // 15 mins 61 ) 62 63 type LocalCacheStore struct { 64 store.Store 65 metrics einterfaces.MetricsInterface 66 cluster einterfaces.ClusterInterface 67 68 reaction LocalCacheReactionStore 69 reactionCache cache.Cache 70 71 fileInfo LocalCacheFileInfoStore 72 fileInfoCache cache.Cache 73 74 role LocalCacheRoleStore 75 roleCache cache.Cache 76 rolePermissionsCache cache.Cache 77 78 scheme LocalCacheSchemeStore 79 schemeCache cache.Cache 80 81 emoji LocalCacheEmojiStore 82 emojiCacheById cache.Cache 83 emojiIdCacheByName cache.Cache 84 85 class LocalCacheClassStore 86 classMemberCountsCache cache.Cache 87 classByIdCache cache.Cache 88 89 webhook LocalCacheWebhookStore 90 webhookCache cache.Cache 91 92 post LocalCachePostStore 93 postLastPostsCache cache.Cache 94 lastPostTimeCache cache.Cache 95 96 user LocalCacheUserStore 97 userProfileByIdsCache cache.Cache 98 profilesInClassCache cache.Cache 99 100 branch LocalCacheBranchStore 101 branchAllBranchIdsForUserCache cache.Cache 102 103 termsOfService LocalCacheTermsOfServiceStore 104 termsOfServiceCache cache.Cache 105 } 106 107 func NewLocalCacheLayer(baseStore store.Store, metrics einterfaces.MetricsInterface, cluster einterfaces.ClusterInterface, cacheProvider cache.Provider) LocalCacheStore { 108 109 localCacheStore := LocalCacheStore{ 110 Store: baseStore, 111 cluster: cluster, 112 metrics: metrics, 113 } 114 // Reactions 115 localCacheStore.reactionCache = cacheProvider.NewCacheWithParams(REACTION_CACHE_SIZE, "Reaction", REACTION_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_REACTIONS) 116 localCacheStore.reaction = LocalCacheReactionStore{ReactionStore: baseStore.Reaction(), rootStore: &localCacheStore} 117 118 // Roles 119 localCacheStore.roleCache = cacheProvider.NewCacheWithParams(ROLE_CACHE_SIZE, "Role", ROLE_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_ROLES) 120 localCacheStore.rolePermissionsCache = cacheProvider.NewCacheWithParams(ROLE_CACHE_SIZE, "RolePermission", ROLE_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_ROLE_PERMISSIONS) 121 localCacheStore.role = LocalCacheRoleStore{RoleStore: baseStore.Role(), rootStore: &localCacheStore} 122 123 // Schemes 124 localCacheStore.schemeCache = cacheProvider.NewCacheWithParams(SCHEME_CACHE_SIZE, "Scheme", SCHEME_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_SCHEMES) 125 localCacheStore.scheme = LocalCacheSchemeStore{SchemeStore: baseStore.Scheme(), rootStore: &localCacheStore} 126 127 // FileInfo 128 localCacheStore.fileInfoCache = cacheProvider.NewCacheWithParams(FILE_INFO_CACHE_SIZE, "FileInfo", FILE_INFO_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_FILE_INFOS) 129 localCacheStore.fileInfo = LocalCacheFileInfoStore{FileInfoStore: baseStore.FileInfo(), rootStore: &localCacheStore} 130 131 // Webhooks 132 localCacheStore.webhookCache = cacheProvider.NewCacheWithParams(WEBHOOK_CACHE_SIZE, "Webhook", WEBHOOK_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_WEBHOOKS) 133 localCacheStore.webhook = LocalCacheWebhookStore{WebhookStore: baseStore.Webhook(), rootStore: &localCacheStore} 134 135 // Emojis 136 localCacheStore.emojiCacheById = cacheProvider.NewCacheWithParams(EMOJI_CACHE_SIZE, "EmojiById", EMOJI_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_EMOJIS_BY_ID) 137 localCacheStore.emojiIdCacheByName = cacheProvider.NewCacheWithParams(EMOJI_CACHE_SIZE, "EmojiByName", EMOJI_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_EMOJIS_ID_BY_NAME) 138 localCacheStore.emoji = LocalCacheEmojiStore{EmojiStore: baseStore.Emoji(), rootStore: &localCacheStore} 139 140 // Classes 141 localCacheStore.classMemberCountsCache = cacheProvider.NewCacheWithParams(CLASS_MEMBERS_COUNTS_CACHE_SIZE, "ClassMemberCounts", CLASS_MEMBERS_COUNTS_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CLASS_MEMBER_COUNTS) 142 localCacheStore.classByIdCache = cacheProvider.NewCacheWithParams(model.CLASS_CACHE_SIZE, "classById", CLASS_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CLASS) 143 localCacheStore.class = LocalCacheClassStore{ClassStore: baseStore.Class(), rootStore: &localCacheStore} 144 145 // Posts 146 localCacheStore.postLastPostsCache = cacheProvider.NewCacheWithParams(LAST_POSTS_CACHE_SIZE, "LastPost", LAST_POSTS_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_LAST_POSTS) 147 localCacheStore.lastPostTimeCache = cacheProvider.NewCacheWithParams(LAST_POST_TIME_CACHE_SIZE, "LastPostTime", LAST_POST_TIME_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_LAST_POST_TIME) 148 localCacheStore.post = LocalCachePostStore{PostStore: baseStore.Post(), rootStore: &localCacheStore} 149 150 // TOS 151 localCacheStore.termsOfServiceCache = cacheProvider.NewCacheWithParams(TERMS_OF_SERVICE_CACHE_SIZE, "TermsOfService", TERMS_OF_SERVICE_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_TERMS_OF_SERVICE) 152 localCacheStore.termsOfService = LocalCacheTermsOfServiceStore{TermsOfServiceStore: baseStore.TermsOfService(), rootStore: &localCacheStore} 153 154 // Users 155 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) 156 localCacheStore.profilesInClassCache = cacheProvider.NewCacheWithParams(PROFILES_IN_CLASS_CACHE_SIZE, "ProfilesInClass", PROFILES_IN_CLASS_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_PROFILE_IN_CLASS) 157 localCacheStore.user = LocalCacheUserStore{UserStore: baseStore.User(), rootStore: &localCacheStore} 158 159 // Branches 160 localCacheStore.branchAllBranchIdsForUserCache = cacheProvider.NewCacheWithParams(BRANCH_CACHE_SIZE, "Branch", BRANCH_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_BRANCHES) 161 localCacheStore.branch = LocalCacheBranchStore{BranchStore: baseStore.Branch(), rootStore: &localCacheStore} 162 163 if cluster != nil { 164 cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_REACTIONS, localCacheStore.reaction.handleClusterInvalidateReaction) 165 cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_ROLES, localCacheStore.role.handleClusterInvalidateRole) 166 cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_ROLE_PERMISSIONS, localCacheStore.role.handleClusterInvalidateRolePermissions) 167 cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_SCHEMES, localCacheStore.scheme.handleClusterInvalidateScheme) 168 cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_FILE_INFOS, localCacheStore.fileInfo.handleClusterInvalidateFileInfo) 169 cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_LAST_POST_TIME, localCacheStore.post.handleClusterInvalidateLastPostTime) 170 cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_WEBHOOKS, localCacheStore.webhook.handleClusterInvalidateWebhook) 171 cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_EMOJIS_BY_ID, localCacheStore.emoji.handleClusterInvalidateEmojiById) 172 cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_EMOJIS_ID_BY_NAME, localCacheStore.emoji.handleClusterInvalidateEmojiIdByName) 173 cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CLASS_MEMBER_COUNTS, localCacheStore.class.handleClusterInvalidateClassMemberCounts) 174 cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CLASS, localCacheStore.class.handleClusterInvalidateClassById) 175 cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_LAST_POSTS, localCacheStore.post.handleClusterInvalidateLastPosts) 176 cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_TERMS_OF_SERVICE, localCacheStore.termsOfService.handleClusterInvalidateTermsOfService) 177 cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_PROFILE_BY_IDS, localCacheStore.user.handleClusterInvalidateScheme) 178 cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_PROFILE_IN_CLASS, localCacheStore.user.handleClusterInvalidateProfilesInClass) 179 cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_BRANCHES, localCacheStore.branch.handleClusterInvalidateBranch) 180 } 181 return localCacheStore 182 } 183 184 func (s LocalCacheStore) Reaction() store.ReactionStore { 185 return s.reaction 186 } 187 188 func (s LocalCacheStore) Role() store.RoleStore { 189 return s.role 190 } 191 192 func (s LocalCacheStore) Scheme() store.SchemeStore { 193 return s.scheme 194 } 195 196 func (s LocalCacheStore) FileInfo() store.FileInfoStore { 197 return s.fileInfo 198 } 199 200 func (s LocalCacheStore) Webhook() store.WebhookStore { 201 return s.webhook 202 } 203 204 func (s LocalCacheStore) Emoji() store.EmojiStore { 205 return s.emoji 206 } 207 208 func (s LocalCacheStore) Class() store.ClassStore { 209 return s.class 210 } 211 212 func (s LocalCacheStore) Post() store.PostStore { 213 return s.post 214 } 215 216 func (s LocalCacheStore) TermsOfService() store.TermsOfServiceStore { 217 return s.termsOfService 218 } 219 220 func (s LocalCacheStore) User() store.UserStore { 221 return s.user 222 } 223 224 func (s LocalCacheStore) Branch() store.BranchStore { 225 return s.branch 226 } 227 228 func (s LocalCacheStore) DropAllTables() { 229 s.Invalidate() 230 s.Store.DropAllTables() 231 } 232 233 func (s *LocalCacheStore) doInvalidateCacheCluster(cache cache.Cache, key string) { 234 cache.Remove(key) 235 if s.cluster != nil { 236 msg := &model.ClusterMessage{ 237 Event: cache.GetInvalidateClusterEvent(), 238 SendType: model.CLUSTER_SEND_BEST_EFFORT, 239 Data: key, 240 } 241 s.cluster.SendClusterMessage(msg) 242 } 243 } 244 245 func (s *LocalCacheStore) doStandardAddToCache(cache cache.Cache, key string, value interface{}) { 246 cache.AddWithDefaultExpires(key, value) 247 } 248 249 func (s *LocalCacheStore) doStandardReadCache(cache cache.Cache, key string) interface{} { 250 if cacheItem, ok := cache.Get(key); ok { 251 if s.metrics != nil { 252 s.metrics.IncrementMemCacheHitCounter(cache.Name()) 253 } 254 return cacheItem 255 } 256 257 if s.metrics != nil { 258 s.metrics.IncrementMemCacheMissCounter(cache.Name()) 259 } 260 261 return nil 262 } 263 264 func (s *LocalCacheStore) doClearCacheCluster(cache cache.Cache) { 265 cache.Purge() 266 if s.cluster != nil { 267 msg := &model.ClusterMessage{ 268 Event: cache.GetInvalidateClusterEvent(), 269 SendType: model.CLUSTER_SEND_BEST_EFFORT, 270 Data: CLEAR_CACHE_MESSAGE_DATA, 271 } 272 s.cluster.SendClusterMessage(msg) 273 } 274 } 275 276 func (s *LocalCacheStore) Invalidate() { 277 s.doClearCacheCluster(s.reactionCache) 278 s.doClearCacheCluster(s.schemeCache) 279 s.doClearCacheCluster(s.roleCache) 280 s.doClearCacheCluster(s.fileInfoCache) 281 s.doClearCacheCluster(s.webhookCache) 282 s.doClearCacheCluster(s.emojiCacheById) 283 s.doClearCacheCluster(s.emojiIdCacheByName) 284 s.doClearCacheCluster(s.classMemberCountsCache) 285 s.doClearCacheCluster(s.classByIdCache) 286 s.doClearCacheCluster(s.postLastPostsCache) 287 s.doClearCacheCluster(s.termsOfServiceCache) 288 s.doClearCacheCluster(s.lastPostTimeCache) 289 s.doClearCacheCluster(s.userProfileByIdsCache) 290 s.doClearCacheCluster(s.profilesInClassCache) 291 s.doClearCacheCluster(s.branchAllBranchIdsForUserCache) 292 s.doClearCacheCluster(s.rolePermissionsCache) 293 }