MM-25115 - make cacheProvider2 accessible to localcachelayer (#14691)

* make cacheProvider2 accessible to localcachelayer

* migrate localcachelayer

* revert test.sh

* workaround gob deserialization issue

* fix web_test.go

* merge conflicts

* resolve merge conflicts

* revert back test workaround

* fix the wrong merge
Этот коммит содержится в:
Siyuan Liu
2020-06-25 04:38:53 -07:00
коммит произвёл GitHub
родитель 1648b11e82
Коммит aaea36a24d
27 изменённых файлов: 484 добавлений и 433 удалений

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

@@ -98,7 +98,7 @@ func setupTestHelper(dbStore store.Store, searchEngine *searchengine.Broker, ent
} }
if includeCache { if includeCache {
// Adds the cache layer to the test store // Adds the cache layer to the test store
s.Store = localcachelayer.NewLocalCacheLayer(s.Store, s.Metrics, s.Cluster, s.CacheProvider) s.Store = localcachelayer.NewLocalCacheLayer(s.Store, s.Metrics, s.Cluster, s.CacheProvider2)
} }
th := &TestHelper{ th := &TestHelper{

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

@@ -76,7 +76,7 @@ func setupTestHelper(dbStore store.Store, enterprise bool, includeCacheLayer boo
if includeCacheLayer { if includeCacheLayer {
// Adds the cache layer to the test store // Adds the cache layer to the test store
s.Store = localcachelayer.NewLocalCacheLayer(s.Store, s.Metrics, s.Cluster, s.CacheProvider) s.Store = localcachelayer.NewLocalCacheLayer(s.Store, s.Metrics, s.Cluster, s.CacheProvider2)
} }
th := &TestHelper{ th := &TestHelper{

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

@@ -320,7 +320,7 @@ func NewServer(options ...Option) (*Server, error) {
s.sqlStore, s.sqlStore,
s.Metrics, s.Metrics,
s.Cluster, s.Cluster,
s.CacheProvider, s.CacheProvider2,
), ),
s.SearchEngine, s.SearchEngine,
s.Config(), s.Config(),

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

@@ -47,7 +47,7 @@ func setupTestHelper(enterprise bool) *TestHelper {
panic(err) panic(err)
} }
// Adds the cache layer to the test store // Adds the cache layer to the test store
s.Store = localcachelayer.NewLocalCacheLayer(s.Store, s.Metrics, s.Cluster, s.CacheProvider) s.Store = localcachelayer.NewLocalCacheLayer(s.Store, s.Metrics, s.Cluster, s.CacheProvider2)
th := &TestHelper{ th := &TestHelper{
App: app.New(app.ServerConnector(s)), App: app.New(app.ServerConnector(s)),

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

@@ -43,4 +43,7 @@ type Cache interface {
// GetInvalidateClusterEvent returns the cluster event configured when this cache was created. // GetInvalidateClusterEvent returns the cluster event configured when this cache was created.
GetInvalidateClusterEvent() string GetInvalidateClusterEvent() string
// Name returns the name of the cache
Name() string
} }

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

@@ -13,6 +13,7 @@ import (
// LRU is a thread-safe fixed size LRU cache. // LRU is a thread-safe fixed size LRU cache.
type LRU struct { type LRU struct {
name string
size int size int
evictList *list.List evictList *list.List
items map[string]*list.Element items map[string]*list.Element
@@ -25,6 +26,7 @@ type LRU struct {
// LRUOptions contains options for initializing LRU cache // LRUOptions contains options for initializing LRU cache
type LRUOptions struct { type LRUOptions struct {
Name string
Size int Size int
DefaultExpiry time.Duration DefaultExpiry time.Duration
InvalidateClusterEvent string InvalidateClusterEvent string
@@ -41,6 +43,7 @@ type entry struct {
// NewLRU creates an LRU of the given size. // NewLRU creates an LRU of the given size.
func NewLRU(opts *LRUOptions) Cache { func NewLRU(opts *LRUOptions) Cache {
return &LRU{ return &LRU{
name: opts.Name,
size: opts.Size, size: opts.Size,
evictList: list.New(), evictList: list.New(),
items: make(map[string]*list.Element, opts.Size), items: make(map[string]*list.Element, opts.Size),
@@ -127,6 +130,11 @@ func (l *LRU) GetInvalidateClusterEvent() string {
return l.invalidateClusterEvent return l.invalidateClusterEvent
} }
// Name returns the name of the cache
func (l *LRU) Name() string {
return l.name
}
func (l *LRU) set(key string, value interface{}, ttl time.Duration) error { func (l *LRU) set(key string, value interface{}, ttl time.Duration) error {
var expires time.Time var expires time.Time
if ttl > 0 { if ttl > 0 {

167
services/cache2/mocks/Cache.go Обычный файл
Просмотреть файл

@@ -0,0 +1,167 @@
// Code generated by mockery v1.0.0. DO NOT EDIT.
package mocks
import mock "github.com/stretchr/testify/mock"
import time "time"
// Cache is an autogenerated mock type for the Cache type
type Cache struct {
mock.Mock
}
// Get provides a mock function with given fields: key, value
func (_m *Cache) Get(key string, value interface{}) error {
ret := _m.Called(key, value)
var r0 error
if rf, ok := ret.Get(0).(func(string, interface{}) error); ok {
r0 = rf(key, value)
} else {
r0 = ret.Error(0)
}
return r0
}
// GetInvalidateClusterEvent provides a mock function with given fields:
func (_m *Cache) GetInvalidateClusterEvent() string {
ret := _m.Called()
var r0 string
if rf, ok := ret.Get(0).(func() string); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(string)
}
return r0
}
// Keys provides a mock function with given fields:
func (_m *Cache) Keys() ([]string, error) {
ret := _m.Called()
var r0 []string
if rf, ok := ret.Get(0).(func() []string); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]string)
}
}
var r1 error
if rf, ok := ret.Get(1).(func() error); ok {
r1 = rf()
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Len provides a mock function with given fields:
func (_m *Cache) Len() (int, error) {
ret := _m.Called()
var r0 int
if rf, ok := ret.Get(0).(func() int); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(int)
}
var r1 error
if rf, ok := ret.Get(1).(func() error); ok {
r1 = rf()
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Name provides a mock function with given fields:
func (_m *Cache) Name() string {
ret := _m.Called()
var r0 string
if rf, ok := ret.Get(0).(func() string); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(string)
}
return r0
}
// Purge provides a mock function with given fields:
func (_m *Cache) Purge() error {
ret := _m.Called()
var r0 error
if rf, ok := ret.Get(0).(func() error); ok {
r0 = rf()
} else {
r0 = ret.Error(0)
}
return r0
}
// Remove provides a mock function with given fields: key
func (_m *Cache) Remove(key string) error {
ret := _m.Called(key)
var r0 error
if rf, ok := ret.Get(0).(func(string) error); ok {
r0 = rf(key)
} else {
r0 = ret.Error(0)
}
return r0
}
// Set provides a mock function with given fields: key, value
func (_m *Cache) Set(key string, value interface{}) error {
ret := _m.Called(key, value)
var r0 error
if rf, ok := ret.Get(0).(func(string, interface{}) error); ok {
r0 = rf(key, value)
} else {
r0 = ret.Error(0)
}
return r0
}
// SetWithDefaultExpiry provides a mock function with given fields: key, value
func (_m *Cache) SetWithDefaultExpiry(key string, value interface{}) error {
ret := _m.Called(key, value)
var r0 error
if rf, ok := ret.Get(0).(func(string, interface{}) error); ok {
r0 = rf(key, value)
} else {
r0 = ret.Error(0)
}
return r0
}
// SetWithExpiry provides a mock function with given fields: key, value, ttl
func (_m *Cache) SetWithExpiry(key string, value interface{}, ttl time.Duration) error {
ret := _m.Called(key, value, ttl)
var r0 error
if rf, ok := ret.Get(0).(func(string, interface{}, time.Duration) error); ok {
r0 = rf(key, value, ttl)
} else {
r0 = ret.Error(0)
}
return r0
}

55
services/cache2/mocks/Provider.go Обычный файл
Просмотреть файл

@@ -0,0 +1,55 @@
// Code generated by mockery v1.0.0. DO NOT EDIT.
package mocks
import cache2 "github.com/mattermost/mattermost-server/v5/services/cache2"
import mock "github.com/stretchr/testify/mock"
// Provider is an autogenerated mock type for the Provider type
type Provider struct {
mock.Mock
}
// Close provides a mock function with given fields:
func (_m *Provider) Close() error {
ret := _m.Called()
var r0 error
if rf, ok := ret.Get(0).(func() error); ok {
r0 = rf()
} else {
r0 = ret.Error(0)
}
return r0
}
// Connect provides a mock function with given fields:
func (_m *Provider) Connect() error {
ret := _m.Called()
var r0 error
if rf, ok := ret.Get(0).(func() error); ok {
r0 = rf()
} else {
r0 = ret.Error(0)
}
return r0
}
// NewCache provides a mock function with given fields: opts
func (_m *Provider) NewCache(opts *cache2.CacheOptions) cache2.Cache {
ret := _m.Called(opts)
var r0 cache2.Cache
if rf, ok := ret.Get(0).(func(*cache2.CacheOptions) cache2.Cache); ok {
r0 = rf(opts)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(cache2.Cache)
}
}
return r0
}

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

@@ -34,6 +34,7 @@ func NewProvider() Provider {
// NewCache creates a new cache with given opts // NewCache creates a new cache with given opts
func (c *cacheProvider) NewCache(opts *CacheOptions) Cache { func (c *cacheProvider) NewCache(opts *CacheOptions) Cache {
return NewLRU(&LRUOptions{ return NewLRU(&LRUOptions{
Name: opts.Name,
Size: opts.Size, Size: opts.Size,
DefaultExpiry: opts.DefaultExpiry, DefaultExpiry: opts.DefaultExpiry,
InvalidateClusterEvent: opts.InvalidateClusterEvent, InvalidateClusterEvent: opts.InvalidateClusterEvent,

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

@@ -89,8 +89,9 @@ func (s LocalCacheChannelStore) InvalidateChannel(channelId string) {
func (s LocalCacheChannelStore) GetMemberCount(channelId string, allowFromCache bool) (int64, *model.AppError) { func (s LocalCacheChannelStore) GetMemberCount(channelId string, allowFromCache bool) (int64, *model.AppError) {
if allowFromCache { if allowFromCache {
if count := s.rootStore.doStandardReadCache(s.rootStore.channelMemberCountsCache, channelId); count != nil { var count int64
return count.(int64), nil if err := s.rootStore.doStandardReadCache(s.rootStore.channelMemberCountsCache, channelId, &count); err == nil {
return count, nil
} }
} }
count, err := s.ChannelStore.GetMemberCount(channelId, allowFromCache) count, err := s.ChannelStore.GetMemberCount(channelId, allowFromCache)
@@ -104,8 +105,9 @@ func (s LocalCacheChannelStore) GetMemberCount(channelId string, allowFromCache
func (s LocalCacheChannelStore) GetGuestCount(channelId string, allowFromCache bool) (int64, *model.AppError) { func (s LocalCacheChannelStore) GetGuestCount(channelId string, allowFromCache bool) (int64, *model.AppError) {
if allowFromCache { if allowFromCache {
if count := s.rootStore.doStandardReadCache(s.rootStore.channelGuestCountCache, channelId); count != nil { var count int64
return count.(int64), nil if err := s.rootStore.doStandardReadCache(s.rootStore.channelGuestCountCache, channelId, &count); err == nil {
return count, nil
} }
} }
count, err := s.ChannelStore.GetGuestCount(channelId, allowFromCache) count, err := s.ChannelStore.GetGuestCount(channelId, allowFromCache)
@@ -118,8 +120,9 @@ func (s LocalCacheChannelStore) GetGuestCount(channelId string, allowFromCache b
} }
func (s LocalCacheChannelStore) GetMemberCountFromCache(channelId string) int64 { func (s LocalCacheChannelStore) GetMemberCountFromCache(channelId string) int64 {
if count := s.rootStore.doStandardReadCache(s.rootStore.channelMemberCountsCache, channelId); count != nil { var count int64
return count.(int64) if err := s.rootStore.doStandardReadCache(s.rootStore.channelMemberCountsCache, channelId, &count); err == nil {
return count
} }
count, err := s.GetMemberCount(channelId, true) count, err := s.GetMemberCount(channelId, true)
@@ -132,8 +135,9 @@ func (s LocalCacheChannelStore) GetMemberCountFromCache(channelId string) int64
func (s LocalCacheChannelStore) GetPinnedPostCount(channelId string, allowFromCache bool) (int64, *model.AppError) { func (s LocalCacheChannelStore) GetPinnedPostCount(channelId string, allowFromCache bool) (int64, *model.AppError) {
if allowFromCache { if allowFromCache {
if count := s.rootStore.doStandardReadCache(s.rootStore.channelPinnedPostCountsCache, channelId); count != nil { var count int64
return count.(int64), nil if err := s.rootStore.doStandardReadCache(s.rootStore.channelPinnedPostCountsCache, channelId, &count); err == nil {
return count, nil
} }
} }
@@ -153,8 +157,9 @@ func (s LocalCacheChannelStore) GetPinnedPostCount(channelId string, allowFromCa
func (s LocalCacheChannelStore) Get(id string, allowFromCache bool) (*model.Channel, error) { func (s LocalCacheChannelStore) Get(id string, allowFromCache bool) (*model.Channel, error) {
if allowFromCache { if allowFromCache {
if cacheItem := s.rootStore.doStandardReadCache(s.rootStore.channelByIdCache, id); cacheItem != nil { var cacheItem *model.Channel
ch := cacheItem.(*model.Channel).DeepCopy() if err := s.rootStore.doStandardReadCache(s.rootStore.channelByIdCache, id, &cacheItem); err == nil {
ch := cacheItem.DeepCopy()
return ch, nil return ch, nil
} }
} }

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

@@ -4,9 +4,10 @@
package localcachelayer package localcachelayer
import ( import (
"github.com/mattermost/mattermost-server/v5/model"
"testing" "testing"
"github.com/mattermost/mattermost-server/v5/model"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"

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

@@ -81,15 +81,17 @@ func (es LocalCacheEmojiStore) addToCache(emoji *model.Emoji) {
} }
func (es LocalCacheEmojiStore) getFromCacheById(id string) (*model.Emoji, bool) { func (es LocalCacheEmojiStore) getFromCacheById(id string) (*model.Emoji, bool) {
if emoji := es.rootStore.doStandardReadCache(es.rootStore.emojiCacheById, id); emoji != nil { var emoji *model.Emoji
return emoji.(*model.Emoji), true if err := es.rootStore.doStandardReadCache(es.rootStore.emojiCacheById, id, &emoji); err == nil {
return emoji, true
} }
return nil, false return nil, false
} }
func (es LocalCacheEmojiStore) getFromCacheByName(name string) (*model.Emoji, bool) { func (es LocalCacheEmojiStore) getFromCacheByName(name string) (*model.Emoji, bool) {
if emojiId := es.rootStore.doStandardReadCache(es.rootStore.emojiIdCacheByName, name); emojiId != nil { var emojiId string
return es.getFromCacheById(emojiId.(string)) if err := es.rootStore.doStandardReadCache(es.rootStore.emojiIdCacheByName, name, &emojiId); err == nil {
return es.getFromCacheById(emojiId)
} }
return nil, false return nil, false
} }

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

@@ -31,8 +31,9 @@ func (s LocalCacheFileInfoStore) GetForPost(postId string, readFromMaster, inclu
cacheKey += "_deleted" cacheKey += "_deleted"
} }
if fileInfo := s.rootStore.doStandardReadCache(s.rootStore.fileInfoCache, cacheKey); fileInfo != nil { var fileInfo []*model.FileInfo
return fileInfo.([]*model.FileInfo), nil if err := s.rootStore.doStandardReadCache(s.rootStore.fileInfoCache, cacheKey, &fileInfo); err == nil {
return fileInfo, nil
} }
fileInfos, err := s.FileInfoStore.GetForPost(postId, readFromMaster, includeDeleted, allowFromCache) fileInfos, err := s.FileInfoStore.GetForPost(postId, readFromMaster, includeDeleted, allowFromCache)

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

@@ -4,9 +4,11 @@
package localcachelayer package localcachelayer
import ( import (
"time"
"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/cache2"
"github.com/mattermost/mattermost-server/v5/store" "github.com/mattermost/mattermost-server/v5/store"
) )
@@ -66,47 +68,47 @@ type LocalCacheStore struct {
cluster einterfaces.ClusterInterface cluster einterfaces.ClusterInterface
reaction LocalCacheReactionStore reaction LocalCacheReactionStore
reactionCache cache.Cache reactionCache cache2.Cache
fileInfo LocalCacheFileInfoStore fileInfo LocalCacheFileInfoStore
fileInfoCache cache.Cache fileInfoCache cache2.Cache
role LocalCacheRoleStore role LocalCacheRoleStore
roleCache cache.Cache roleCache cache2.Cache
rolePermissionsCache cache.Cache rolePermissionsCache cache2.Cache
scheme LocalCacheSchemeStore scheme LocalCacheSchemeStore
schemeCache cache.Cache schemeCache cache2.Cache
emoji LocalCacheEmojiStore emoji LocalCacheEmojiStore
emojiCacheById cache.Cache emojiCacheById cache2.Cache
emojiIdCacheByName cache.Cache emojiIdCacheByName cache2.Cache
channel LocalCacheChannelStore channel LocalCacheChannelStore
channelMemberCountsCache cache.Cache channelMemberCountsCache cache2.Cache
channelGuestCountCache cache.Cache channelGuestCountCache cache2.Cache
channelPinnedPostCountsCache cache.Cache channelPinnedPostCountsCache cache2.Cache
channelByIdCache cache.Cache channelByIdCache cache2.Cache
webhook LocalCacheWebhookStore webhook LocalCacheWebhookStore
webhookCache cache.Cache webhookCache cache2.Cache
post LocalCachePostStore post LocalCachePostStore
postLastPostsCache cache.Cache postLastPostsCache cache2.Cache
lastPostTimeCache cache.Cache lastPostTimeCache cache2.Cache
user LocalCacheUserStore user LocalCacheUserStore
userProfileByIdsCache cache.Cache userProfileByIdsCache cache2.Cache
profilesInChannelCache cache.Cache profilesInChannelCache cache2.Cache
team LocalCacheTeamStore team LocalCacheTeamStore
teamAllTeamIdsForUserCache cache.Cache teamAllTeamIdsForUserCache cache2.Cache
termsOfService LocalCacheTermsOfServiceStore termsOfService LocalCacheTermsOfServiceStore
termsOfServiceCache cache.Cache termsOfServiceCache cache2.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 cache2.Provider) LocalCacheStore {
localCacheStore := LocalCacheStore{ localCacheStore := LocalCacheStore{
Store: baseStore, Store: baseStore,
@@ -114,54 +116,144 @@ func NewLocalCacheLayer(baseStore store.Store, metrics einterfaces.MetricsInterf
metrics: metrics, metrics: metrics,
} }
// Reactions // Reactions
localCacheStore.reactionCache = cacheProvider.NewCacheWithParams(REACTION_CACHE_SIZE, "Reaction", REACTION_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_REACTIONS) localCacheStore.reactionCache = cacheProvider.NewCache(&cache2.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} localCacheStore.reaction = LocalCacheReactionStore{ReactionStore: baseStore.Reaction(), rootStore: &localCacheStore}
// Roles // Roles
localCacheStore.roleCache = cacheProvider.NewCacheWithParams(ROLE_CACHE_SIZE, "Role", ROLE_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_ROLES) localCacheStore.roleCache = cacheProvider.NewCache(&cache2.CacheOptions{
localCacheStore.rolePermissionsCache = cacheProvider.NewCacheWithParams(ROLE_CACHE_SIZE, "RolePermission", ROLE_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_ROLE_PERMISSIONS) Size: ROLE_CACHE_SIZE,
Name: "Role",
DefaultExpiry: ROLE_CACHE_SEC * time.Second,
InvalidateClusterEvent: model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_ROLES,
})
localCacheStore.rolePermissionsCache = cacheProvider.NewCache(&cache2.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} localCacheStore.role = LocalCacheRoleStore{RoleStore: baseStore.Role(), rootStore: &localCacheStore}
// Schemes // Schemes
localCacheStore.schemeCache = cacheProvider.NewCacheWithParams(SCHEME_CACHE_SIZE, "Scheme", SCHEME_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_SCHEMES) localCacheStore.schemeCache = cacheProvider.NewCache(&cache2.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} localCacheStore.scheme = LocalCacheSchemeStore{SchemeStore: baseStore.Scheme(), rootStore: &localCacheStore}
// FileInfo // FileInfo
localCacheStore.fileInfoCache = cacheProvider.NewCacheWithParams(FILE_INFO_CACHE_SIZE, "FileInfo", FILE_INFO_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_FILE_INFOS) localCacheStore.fileInfoCache = cacheProvider.NewCache(&cache2.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} localCacheStore.fileInfo = LocalCacheFileInfoStore{FileInfoStore: baseStore.FileInfo(), rootStore: &localCacheStore}
// Webhooks // Webhooks
localCacheStore.webhookCache = cacheProvider.NewCacheWithParams(WEBHOOK_CACHE_SIZE, "Webhook", WEBHOOK_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_WEBHOOKS) localCacheStore.webhookCache = cacheProvider.NewCache(&cache2.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} localCacheStore.webhook = LocalCacheWebhookStore{WebhookStore: baseStore.Webhook(), rootStore: &localCacheStore}
// Emojis // Emojis
localCacheStore.emojiCacheById = cacheProvider.NewCacheWithParams(EMOJI_CACHE_SIZE, "EmojiById", EMOJI_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_EMOJIS_BY_ID) localCacheStore.emojiCacheById = cacheProvider.NewCache(&cache2.CacheOptions{
localCacheStore.emojiIdCacheByName = cacheProvider.NewCacheWithParams(EMOJI_CACHE_SIZE, "EmojiByName", EMOJI_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_EMOJIS_ID_BY_NAME) 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(&cache2.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} localCacheStore.emoji = LocalCacheEmojiStore{EmojiStore: baseStore.Emoji(), rootStore: &localCacheStore}
// Channels // Channels
localCacheStore.channelPinnedPostCountsCache = cacheProvider.NewCacheWithParams(CHANNEL_PINNEDPOSTS_COUNTS_CACHE_SIZE, "ChannelPinnedPostsCounts", CHANNEL_PINNEDPOSTS_COUNTS_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_PINNEDPOSTS_COUNTS) localCacheStore.channelPinnedPostCountsCache = cacheProvider.NewCache(&cache2.CacheOptions{
localCacheStore.channelMemberCountsCache = cacheProvider.NewCacheWithParams(CHANNEL_MEMBERS_COUNTS_CACHE_SIZE, "ChannelMemberCounts", CHANNEL_MEMBERS_COUNTS_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_MEMBER_COUNTS) Size: CHANNEL_PINNEDPOSTS_COUNTS_CACHE_SIZE,
localCacheStore.channelGuestCountCache = cacheProvider.NewCacheWithParams(CHANNEL_GUEST_COUNT_CACHE_SIZE, "ChannelGuestsCount", CHANNEL_GUEST_COUNT_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_GUEST_COUNT) Name: "ChannelPinnedPostsCounts",
localCacheStore.channelByIdCache = cacheProvider.NewCacheWithParams(model.CHANNEL_CACHE_SIZE, "channelById", CHANNEL_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL) DefaultExpiry: CHANNEL_PINNEDPOSTS_COUNTS_CACHE_SEC * time.Second,
InvalidateClusterEvent: model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_CHANNEL_PINNEDPOSTS_COUNTS,
})
localCacheStore.channelMemberCountsCache = cacheProvider.NewCache(&cache2.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(&cache2.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(&cache2.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} localCacheStore.channel = LocalCacheChannelStore{ChannelStore: baseStore.Channel(), rootStore: &localCacheStore}
// Posts // Posts
localCacheStore.postLastPostsCache = cacheProvider.NewCacheWithParams(LAST_POSTS_CACHE_SIZE, "LastPost", LAST_POSTS_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_LAST_POSTS) localCacheStore.postLastPostsCache = cacheProvider.NewCache(&cache2.CacheOptions{
localCacheStore.lastPostTimeCache = cacheProvider.NewCacheWithParams(LAST_POST_TIME_CACHE_SIZE, "LastPostTime", LAST_POST_TIME_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_LAST_POST_TIME) 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(&cache2.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} localCacheStore.post = LocalCachePostStore{PostStore: baseStore.Post(), rootStore: &localCacheStore}
// TOS // TOS
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.NewCache(&cache2.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} localCacheStore.termsOfService = LocalCacheTermsOfServiceStore{TermsOfServiceStore: baseStore.TermsOfService(), rootStore: &localCacheStore}
// Users // Users
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.NewCache(&cache2.CacheOptions{
localCacheStore.profilesInChannelCache = cacheProvider.NewCacheWithParams(PROFILES_IN_CHANNEL_CACHE_SIZE, "ProfilesInChannel", PROFILES_IN_CHANNEL_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_PROFILE_IN_CHANNEL) 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(&cache2.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} localCacheStore.user = LocalCacheUserStore{UserStore: baseStore.User(), rootStore: &localCacheStore}
// Teams // Teams
localCacheStore.teamAllTeamIdsForUserCache = cacheProvider.NewCacheWithParams(TEAM_CACHE_SIZE, "Team", TEAM_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_TEAMS) localCacheStore.teamAllTeamIdsForUserCache = cacheProvider.NewCache(&cache2.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} localCacheStore.team = LocalCacheTeamStore{TeamStore: baseStore.Team(), rootStore: &localCacheStore}
if cluster != nil { if cluster != nil {
@@ -236,7 +328,7 @@ func (s LocalCacheStore) DropAllTables() {
s.Store.DropAllTables() s.Store.DropAllTables()
} }
func (s *LocalCacheStore) doInvalidateCacheCluster(cache cache.Cache, key string) { func (s *LocalCacheStore) doInvalidateCacheCluster(cache cache2.Cache, key string) {
cache.Remove(key) cache.Remove(key)
if s.cluster != nil { if s.cluster != nil {
msg := &model.ClusterMessage{ msg := &model.ClusterMessage{
@@ -248,26 +340,25 @@ func (s *LocalCacheStore) doInvalidateCacheCluster(cache cache.Cache, key string
} }
} }
func (s *LocalCacheStore) doStandardAddToCache(cache cache.Cache, key string, value interface{}) { func (s *LocalCacheStore) doStandardAddToCache(cache cache2.Cache, key string, value interface{}) {
cache.AddWithDefaultExpires(key, value) cache.SetWithDefaultExpiry(key, value)
} }
func (s *LocalCacheStore) doStandardReadCache(cache cache.Cache, key string) interface{} { func (s *LocalCacheStore) doStandardReadCache(cache cache2.Cache, key string, value interface{}) error {
if cacheItem, ok := cache.Get(key); ok { if err := cache.Get(key, value); err == nil {
if s.metrics != nil { if s.metrics != nil {
s.metrics.IncrementMemCacheHitCounter(cache.Name()) s.metrics.IncrementMemCacheHitCounter(cache.Name())
} }
return cacheItem return nil
} else {
if s.metrics != nil {
s.metrics.IncrementMemCacheMissCounter(cache.Name())
}
return err
} }
if s.metrics != nil {
s.metrics.IncrementMemCacheMissCounter(cache.Name())
}
return nil
} }
func (s *LocalCacheStore) doClearCacheCluster(cache cache.Cache) { func (s *LocalCacheStore) doClearCacheCluster(cache cache2.Cache) {
cache.Purge() cache.Purge()
if s.cluster != nil { if s.cluster != nil {
msg := &model.ClusterMessage{ msg := &model.ClusterMessage{

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

@@ -7,8 +7,10 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/mattermost/mattermost-server/v5/services/cache2"
"github.com/mattermost/mattermost-server/v5/model" "github.com/mattermost/mattermost-server/v5/model"
"github.com/mattermost/mattermost-server/v5/services/cache/lru" cachemocks "github.com/mattermost/mattermost-server/v5/services/cache2/mocks"
"github.com/mattermost/mattermost-server/v5/store" "github.com/mattermost/mattermost-server/v5/store"
"github.com/mattermost/mattermost-server/v5/store/storetest/mocks" "github.com/mattermost/mattermost-server/v5/store/storetest/mocks"
"github.com/mattermost/mattermost-server/v5/testlib" "github.com/mattermost/mattermost-server/v5/testlib"
@@ -17,117 +19,10 @@ import (
var mainHelper *testlib.MainHelper var mainHelper *testlib.MainHelper
func getMockCacheProvider() *mocks.CacheProvider { func getMockCacheProvider() cache2.Provider {
mockCacheProvider := mocks.CacheProvider{} mockCacheProvider := cachemocks.Provider{}
//todo: replace this line with mocks for all tests mockCacheProvider.On("NewCache", mock.Anything).
mockCacheProvider.On("NewCacheWithParams", Return(cache2.NewLRU(&cache2.LRUOptions{Size: 128}))
mock.AnythingOfType("int"),
"Reaction",
mock.AnythingOfType("int64"),
mock.AnythingOfType("string")).Return(lru.New(128))
mockCacheProvider.On("NewCacheWithParams",
mock.AnythingOfType("int"),
"Role",
mock.AnythingOfType("int64"),
mock.AnythingOfType("string")).Return(lru.New(128))
mockCacheProvider.On("NewCacheWithParams",
mock.AnythingOfType("int"),
"RolePermission",
mock.AnythingOfType("int64"),
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))
mockCacheProvider.On("NewCacheWithParams",
mock.AnythingOfType("int"),
"FileInfo",
mock.AnythingOfType("int64"),
mock.AnythingOfType("string")).Return(lru.New(128))
return &mockCacheProvider return &mockCacheProvider
} }
@@ -230,7 +125,11 @@ func getMockStore() *mocks.Store {
mockTermsOfServiceStore.On("Get", "123", false).Return(&fakeTermsOfService, nil) mockTermsOfServiceStore.On("Get", "123", false).Return(&fakeTermsOfService, nil)
mockStore.On("TermsOfService").Return(&mockTermsOfServiceStore) mockStore.On("TermsOfService").Return(&mockTermsOfServiceStore)
fakeUser := []*model.User{{Id: "123", AuthData: model.NewString("")}} fakeUser := []*model.User{{
Id: "123",
AuthData: model.NewString("authData"),
AuthService: "authService",
}}
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)

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

@@ -62,8 +62,9 @@ func (s LocalCachePostStore) InvalidateLastPostTimeCache(channelId string) {
func (s LocalCachePostStore) GetEtag(channelId string, allowFromCache bool) string { func (s LocalCachePostStore) GetEtag(channelId string, allowFromCache bool) string {
if allowFromCache { if allowFromCache {
if lastTime := s.rootStore.doStandardReadCache(s.rootStore.lastPostTimeCache, channelId); lastTime != nil { var lastTime int64
return fmt.Sprintf("%v.%v", model.CurrentVersion, lastTime.(int64)) if err := s.rootStore.doStandardReadCache(s.rootStore.lastPostTimeCache, channelId, &lastTime); err == nil {
return fmt.Sprintf("%v.%v", model.CurrentVersion, lastTime)
} }
} }
@@ -82,7 +83,8 @@ func (s LocalCachePostStore) GetPostsSince(options model.GetPostsSinceOptions, a
if allowFromCache { if allowFromCache {
// If the last post in the channel's time is less than or equal to the time we are getting posts since, // If the last post in the channel's time is less than or equal to the time we are getting posts since,
// we can safely return no posts. // we can safely return no posts.
if lastTime := s.rootStore.doStandardReadCache(s.rootStore.lastPostTimeCache, options.ChannelId); lastTime != nil && lastTime.(int64) <= options.Time { var lastTime int64
if err := s.rootStore.doStandardReadCache(s.rootStore.lastPostTimeCache, options.ChannelId, &lastTime); err == nil && lastTime <= options.Time {
list := model.NewPostList() list := model.NewPostList()
return list, nil return list, nil
} }
@@ -111,8 +113,9 @@ func (s LocalCachePostStore) GetPosts(options model.GetPostsOptions, allowFromCa
offset := options.PerPage * options.Page offset := options.PerPage * options.Page
// Caching only occurs on limits of 30 and 60, the common limits requested by MM clients // Caching only occurs on limits of 30 and 60, the common limits requested by MM clients
if offset == 0 && (options.PerPage == 60 || options.PerPage == 30) { if offset == 0 && (options.PerPage == 60 || options.PerPage == 30) {
if cacheItem := s.rootStore.doStandardReadCache(s.rootStore.postLastPostsCache, fmt.Sprintf("%s%v", options.ChannelId, options.PerPage)); cacheItem != nil { var cacheItem *model.PostList
return cacheItem.(*model.PostList), nil if err := s.rootStore.doStandardReadCache(s.rootStore.postLastPostsCache, fmt.Sprintf("%s%v", options.ChannelId, options.PerPage), &cacheItem); err == nil {
return cacheItem, nil
} }
} }

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

@@ -36,8 +36,9 @@ func (s LocalCacheReactionStore) GetForPost(postId string, allowFromCache bool)
return s.ReactionStore.GetForPost(postId, false) return s.ReactionStore.GetForPost(postId, false)
} }
if reaction := s.rootStore.doStandardReadCache(s.rootStore.reactionCache, postId); reaction != nil { var reaction []*model.Reaction
return reaction.([]*model.Reaction), nil if err := s.rootStore.doStandardReadCache(s.rootStore.reactionCache, postId, &reaction); err == nil {
return reaction, nil
} }
reaction, err := s.ReactionStore.GetForPost(postId, false) reaction, err := s.ReactionStore.GetForPost(postId, false)

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

@@ -41,8 +41,9 @@ func (s LocalCacheRoleStore) Save(role *model.Role) (*model.Role, *model.AppErro
} }
func (s LocalCacheRoleStore) GetByName(name string) (*model.Role, *model.AppError) { func (s LocalCacheRoleStore) GetByName(name string) (*model.Role, *model.AppError) {
if role := s.rootStore.doStandardReadCache(s.rootStore.roleCache, name); role != nil { var role *model.Role
return role.(*model.Role), nil if err := s.rootStore.doStandardReadCache(s.rootStore.roleCache, name, &role); err == nil {
return role, nil
} }
role, err := s.RoleStore.GetByName(name) role, err := s.RoleStore.GetByName(name)
@@ -58,8 +59,9 @@ func (s LocalCacheRoleStore) GetByNames(names []string) ([]*model.Role, *model.A
var rolesToQuery []string var rolesToQuery []string
for _, roleName := range names { for _, roleName := range names {
if role := s.rootStore.doStandardReadCache(s.rootStore.roleCache, roleName); role != nil { var role *model.Role
foundRoles = append(foundRoles, role.(*model.Role)) if err := s.rootStore.doStandardReadCache(s.rootStore.roleCache, roleName, &role); err == nil {
foundRoles = append(foundRoles, role)
} else { } else {
rolesToQuery = append(rolesToQuery, roleName) rolesToQuery = append(rolesToQuery, roleName)
} }
@@ -95,8 +97,9 @@ func (s LocalCacheRoleStore) PermanentDeleteAll() *model.AppError {
func (s LocalCacheRoleStore) ChannelHigherScopedPermissions(roleNames []string) (map[string]*model.RolePermissions, *model.AppError) { func (s LocalCacheRoleStore) ChannelHigherScopedPermissions(roleNames []string) (map[string]*model.RolePermissions, *model.AppError) {
sort.Strings(roleNames) sort.Strings(roleNames)
cacheKey := strings.Join(roleNames, "/") cacheKey := strings.Join(roleNames, "/")
if rolePermissionsMap := s.rootStore.doStandardReadCache(s.rootStore.rolePermissionsCache, cacheKey); rolePermissionsMap != nil { var rolePermissionsMap map[string]*model.RolePermissions
return rolePermissionsMap.(map[string]*model.RolePermissions), nil if err := s.rootStore.doStandardReadCache(s.rootStore.rolePermissionsCache, cacheKey, &rolePermissionsMap); err == nil {
return rolePermissionsMap, nil
} }
rolePermissionsMap, err := s.RoleStore.ChannelHigherScopedPermissions(roleNames) rolePermissionsMap, err := s.RoleStore.ChannelHigherScopedPermissions(roleNames)

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

@@ -29,8 +29,9 @@ func (s LocalCacheSchemeStore) Save(scheme *model.Scheme) (*model.Scheme, error)
} }
func (s LocalCacheSchemeStore) Get(schemeId string) (*model.Scheme, error) { func (s LocalCacheSchemeStore) Get(schemeId string) (*model.Scheme, error) {
if scheme := s.rootStore.doStandardReadCache(s.rootStore.schemeCache, schemeId); scheme != nil { var scheme *model.Scheme
return scheme.(*model.Scheme), nil if err := s.rootStore.doStandardReadCache(s.rootStore.schemeCache, schemeId, &scheme); err == nil {
return scheme, nil
} }
scheme, err := s.SchemeStore.Get(schemeId) scheme, err := s.SchemeStore.Get(schemeId)

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

@@ -40,8 +40,9 @@ func (s LocalCacheTeamStore) GetUserTeamIds(userID string, allowFromCache bool)
return s.TeamStore.GetUserTeamIds(userID, allowFromCache) return s.TeamStore.GetUserTeamIds(userID, allowFromCache)
} }
if userTeamIds := s.rootStore.doStandardReadCache(s.rootStore.teamAllTeamIdsForUserCache, userID); userTeamIds != nil { var userTeamIds []string
return userTeamIds.([]string), nil if err := s.rootStore.doStandardReadCache(s.rootStore.teamAllTeamIdsForUserCache, userID, &userTeamIds); err == nil {
return userTeamIds, nil
} }
userTeamIds, err := s.TeamStore.GetUserTeamIds(userID, allowFromCache) userTeamIds, err := s.TeamStore.GetUserTeamIds(userID, allowFromCache)

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

@@ -45,9 +45,10 @@ func (s LocalCacheTermsOfServiceStore) Save(termsOfService *model.TermsOfService
func (s LocalCacheTermsOfServiceStore) GetLatest(allowFromCache bool) (*model.TermsOfService, error) { func (s LocalCacheTermsOfServiceStore) GetLatest(allowFromCache bool) (*model.TermsOfService, error) {
if allowFromCache { if allowFromCache {
if s.rootStore.termsOfServiceCache.Len() != 0 { if len, err := s.rootStore.termsOfServiceCache.Len(); err == nil && len != 0 {
if cacheItem := s.rootStore.doStandardReadCache(s.rootStore.termsOfServiceCache, LATEST_KEY); cacheItem != nil { var cacheItem *model.TermsOfService
return cacheItem.(*model.TermsOfService), nil if err := s.rootStore.doStandardReadCache(s.rootStore.termsOfServiceCache, LATEST_KEY, &cacheItem); err == nil {
return cacheItem, nil
} }
} }
} }
@@ -64,8 +65,9 @@ func (s LocalCacheTermsOfServiceStore) GetLatest(allowFromCache bool) (*model.Te
func (s LocalCacheTermsOfServiceStore) Get(id string, allowFromCache bool) (*model.TermsOfService, error) { func (s LocalCacheTermsOfServiceStore) Get(id string, allowFromCache bool) (*model.TermsOfService, error) {
if allowFromCache { if allowFromCache {
if cacheItem := s.rootStore.doStandardReadCache(s.rootStore.termsOfServiceCache, id); cacheItem != nil { var cacheItem *model.TermsOfService
return cacheItem.(*model.TermsOfService), nil if err := s.rootStore.doStandardReadCache(s.rootStore.termsOfServiceCache, id, &cacheItem); err == nil {
return cacheItem, nil
} }
} }

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

@@ -48,15 +48,16 @@ func (s LocalCacheUserStore) InvalidateProfileCacheForUser(userId string) {
} }
func (s LocalCacheUserStore) InvalidateProfilesInChannelCacheByUser(userId string) { func (s LocalCacheUserStore) InvalidateProfilesInChannelCacheByUser(userId string) {
keys := s.rootStore.profilesInChannelCache.Keys() keys, err := s.rootStore.profilesInChannelCache.Keys()
if err == nil {
for _, key := range keys { for _, key := range keys {
if cacheItem, ok := s.rootStore.profilesInChannelCache.Get(key); ok { var userMap map[string]*model.User
userMap := cacheItem.(map[string]*model.User) if err = s.rootStore.profilesInChannelCache.Get(key, &userMap); err == nil {
if _, userInCache := userMap[userId]; userInCache { if _, userInCache := userMap[userId]; userInCache {
s.rootStore.doInvalidateCacheCluster(s.rootStore.profilesInChannelCache, key) s.rootStore.doInvalidateCacheCluster(s.rootStore.profilesInChannelCache, key)
if s.rootStore.metrics != nil { if s.rootStore.metrics != nil {
s.rootStore.metrics.IncrementMemCacheInvalidationCounter("Profiles in Channel - Remove by User") s.rootStore.metrics.IncrementMemCacheInvalidationCounter("Profiles in Channel - Remove by User")
}
} }
} }
} }
@@ -72,8 +73,8 @@ func (s LocalCacheUserStore) InvalidateProfilesInChannelCache(channelId string)
func (s LocalCacheUserStore) GetAllProfilesInChannel(channelId string, allowFromCache bool) (map[string]*model.User, *model.AppError) { func (s LocalCacheUserStore) GetAllProfilesInChannel(channelId string, allowFromCache bool) (map[string]*model.User, *model.AppError) {
if allowFromCache { if allowFromCache {
if cacheItem := s.rootStore.doStandardReadCache(s.rootStore.profilesInChannelCache, channelId); cacheItem != nil { var cachedMap map[string]*model.User
cachedMap := cacheItem.(map[string]*model.User) if err := s.rootStore.doStandardReadCache(s.rootStore.profilesInChannelCache, channelId, &cachedMap); err == nil {
return deepCopyUserMap(cachedMap), nil return deepCopyUserMap(cachedMap), nil
} }
} }
@@ -103,10 +104,10 @@ func (s LocalCacheUserStore) GetProfileByIds(userIds []string, options *store.Us
remainingUserIds := make([]string, 0) remainingUserIds := make([]string, 0)
for _, userId := range userIds { for _, userId := range userIds {
if cacheItem := s.rootStore.doStandardReadCache(s.rootStore.userProfileByIdsCache, userId); cacheItem != nil { var cacheItem *model.User
u := cacheItem.(*model.User) if err := s.rootStore.doStandardReadCache(s.rootStore.userProfileByIdsCache, userId, &cacheItem); err == nil {
if options.Since == 0 || u.UpdateAt > options.Since { if options.Since == 0 || cacheItem.UpdateAt > options.Since {
users = append(users, u.DeepCopy()) users = append(users, cacheItem.DeepCopy())
} }
} else { } else {
remainingUserIds = append(remainingUserIds, userId) remainingUserIds = append(remainingUserIds, userId)
@@ -137,13 +138,12 @@ func (s LocalCacheUserStore) GetProfileByIds(userIds []string, options *store.Us
// if it is present. Otherwise, it fetches the entry from the store and stores it in the // if it is present. Otherwise, it fetches the entry from the store and stores it in the
// cache. // cache.
func (s LocalCacheUserStore) Get(id string) (*model.User, *model.AppError) { func (s LocalCacheUserStore) Get(id string) (*model.User, *model.AppError) {
cacheItem := s.rootStore.doStandardReadCache(s.rootStore.userProfileByIdsCache, id) var cacheItem *model.User
if cacheItem != nil { if err := s.rootStore.doStandardReadCache(s.rootStore.userProfileByIdsCache, id, &cacheItem); err == nil {
if s.rootStore.metrics != nil { if s.rootStore.metrics != nil {
s.rootStore.metrics.AddMemCacheHitCounter("Profile By Id", float64(1)) s.rootStore.metrics.AddMemCacheHitCounter("Profile By Id", float64(1))
} }
u := cacheItem.(*model.User) return cacheItem.DeepCopy(), nil
return u.DeepCopy(), nil
} }
if s.rootStore.metrics != nil { if s.rootStore.metrics != nil {
s.rootStore.metrics.AddMemCacheMissCounter("Profile By Id", float64(1)) s.rootStore.metrics.AddMemCacheMissCounter("Profile By Id", float64(1))

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

@@ -21,7 +21,11 @@ func TestUserStore(t *testing.T) {
func TestUserStoreCache(t *testing.T) { func TestUserStoreCache(t *testing.T) {
fakeUserIds := []string{"123"} fakeUserIds := []string{"123"}
fakeUser := []*model.User{{Id: "123", AuthData: model.NewString("")}} fakeUser := []*model.User{{
Id: "123",
AuthData: model.NewString("authData"),
AuthService: "authService",
}}
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()
@@ -181,7 +185,11 @@ func TestUserStoreProfilesInChannelCache(t *testing.T) {
func TestUserStoreGetCache(t *testing.T) { func TestUserStoreGetCache(t *testing.T) {
fakeUserId := "123" fakeUserId := "123"
fakeUser := &model.User{Id: "123", AuthData: model.NewString("")} fakeUser := &model.User{
Id: "123",
AuthData: model.NewString("authData"),
AuthService: "authService",
}
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()

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

@@ -41,8 +41,9 @@ func (s LocalCacheWebhookStore) GetIncoming(id string, allowFromCache bool) (*mo
return s.WebhookStore.GetIncoming(id, allowFromCache) return s.WebhookStore.GetIncoming(id, allowFromCache)
} }
if incomingWebhook := s.rootStore.doStandardReadCache(s.rootStore.webhookCache, id); incomingWebhook != nil { var incomingWebhook *model.IncomingWebhook
return incomingWebhook.(*model.IncomingWebhook), nil if err := s.rootStore.doStandardReadCache(s.rootStore.webhookCache, id, &incomingWebhook); err == nil {
return incomingWebhook, nil
} }
incomingWebhook, err := s.WebhookStore.GetIncoming(id, allowFromCache) incomingWebhook, err := s.WebhookStore.GetIncoming(id, allowFromCache)

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

@@ -1,145 +0,0 @@
// Code generated by mockery v1.0.0. DO NOT EDIT.
// Regenerate this file using `make store-mocks`.
package mocks
import (
mock "github.com/stretchr/testify/mock"
time "time"
)
// Cache is an autogenerated mock type for the Cache type
type Cache struct {
mock.Mock
}
// Add provides a mock function with given fields: key, value
func (_m *Cache) Add(key interface{}, value interface{}) {
_m.Called(key, value)
}
// AddWithDefaultExpires provides a mock function with given fields: key, value
func (_m *Cache) AddWithDefaultExpires(key interface{}, value interface{}) {
_m.Called(key, value)
}
// AddWithExpiresInSecs provides a mock function with given fields: key, value, expireAtSecs
func (_m *Cache) AddWithExpiresInSecs(key interface{}, value interface{}, expireAtSecs int64) {
_m.Called(key, value, expireAtSecs)
}
// Get provides a mock function with given fields: key
func (_m *Cache) Get(key interface{}) (interface{}, bool) {
ret := _m.Called(key)
var r0 interface{}
if rf, ok := ret.Get(0).(func(interface{}) interface{}); ok {
r0 = rf(key)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(interface{})
}
}
var r1 bool
if rf, ok := ret.Get(1).(func(interface{}) bool); ok {
r1 = rf(key)
} else {
r1 = ret.Get(1).(bool)
}
return r0, r1
}
// GetInvalidateClusterEvent provides a mock function with given fields:
func (_m *Cache) GetInvalidateClusterEvent() string {
ret := _m.Called()
var r0 string
if rf, ok := ret.Get(0).(func() string); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(string)
}
return r0
}
// GetOrAdd provides a mock function with given fields: key, value, ttl
func (_m *Cache) GetOrAdd(key interface{}, value interface{}, ttl time.Duration) (interface{}, bool) {
ret := _m.Called(key, value, ttl)
var r0 interface{}
if rf, ok := ret.Get(0).(func(interface{}, interface{}, time.Duration) interface{}); ok {
r0 = rf(key, value, ttl)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(interface{})
}
}
var r1 bool
if rf, ok := ret.Get(1).(func(interface{}, interface{}, time.Duration) bool); ok {
r1 = rf(key, value, ttl)
} else {
r1 = ret.Get(1).(bool)
}
return r0, r1
}
// Keys provides a mock function with given fields:
func (_m *Cache) Keys() []interface{} {
ret := _m.Called()
var r0 []interface{}
if rf, ok := ret.Get(0).(func() []interface{}); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]interface{})
}
}
return r0
}
// Len provides a mock function with given fields:
func (_m *Cache) Len() int {
ret := _m.Called()
var r0 int
if rf, ok := ret.Get(0).(func() int); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(int)
}
return r0
}
// Name provides a mock function with given fields:
func (_m *Cache) Name() string {
ret := _m.Called()
var r0 string
if rf, ok := ret.Get(0).(func() string); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(string)
}
return r0
}
// Purge provides a mock function with given fields:
func (_m *Cache) Purge() {
_m.Called()
}
// Remove provides a mock function with given fields: key
func (_m *Cache) Remove(key interface{}) {
_m.Called(key)
}

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

@@ -1,57 +0,0 @@
// Code generated by mockery v1.0.0. DO NOT EDIT.
// Regenerate this file using `make store-mocks`.
package mocks
import (
cache "github.com/mattermost/mattermost-server/v5/services/cache"
mock "github.com/stretchr/testify/mock"
)
// CacheProvider is an autogenerated mock type for the CacheProvider type
type CacheProvider struct {
mock.Mock
}
// NewCache provides a mock function with given fields: size
func (_m *CacheProvider) NewCache(size int) cache.Cache {
ret := _m.Called(size)
var r0 cache.Cache
if rf, ok := ret.Get(0).(func(int) cache.Cache); ok {
r0 = rf(size)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(cache.Cache)
}
}
return r0
}
// Connect provides a mock function with given fields:
func (_m *CacheProvider) Connect() {
_m.Called()
}
// Close provides a mock function with given fields:
func (_m *CacheProvider) Close() {
_m.Called()
}
// NewCacheWithParams provides a mock function with given fields: size, name, defaultExpiry, invalidateClusterEvent
func (_m *CacheProvider) NewCacheWithParams(size int, name string, defaultExpiry int64, invalidateClusterEvent string) cache.Cache {
ret := _m.Called(size, name, defaultExpiry, invalidateClusterEvent)
var r0 cache.Cache
if rf, ok := ret.Get(0).(func(int, string, int64, string) cache.Cache); ok {
r0 = rf(size, name, defaultExpiry, invalidateClusterEvent)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(cache.Cache)
}
}
return r0
}

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

@@ -82,7 +82,7 @@ func setupTestHelper(t testing.TB, store store.Store, includeCacheLayer bool) *T
} }
if includeCacheLayer { if includeCacheLayer {
// Adds the cache layer to the test store // Adds the cache layer to the test store
s.Store = localcachelayer.NewLocalCacheLayer(s.Store, s.Metrics, s.Cluster, s.CacheProvider) s.Store = localcachelayer.NewLocalCacheLayer(s.Store, s.Metrics, s.Cluster, s.CacheProvider2)
} }
prevListenAddress := *s.Config().ServiceSettings.ListenAddress prevListenAddress := *s.Config().ServiceSettings.ListenAddress