Initial cache migration to new layers system (#11878)
* Initial cache migration to new layers system * Fixing wrong change * Remove unneeded constants * Remove unneeded file * Adding license headers
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
bd152c6534
Коммит
f8ad9f3b8f
@@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/mattermost/mattermost-server/model"
|
"github.com/mattermost/mattermost-server/model"
|
||||||
"github.com/mattermost/mattermost-server/services/mailservice"
|
"github.com/mattermost/mattermost-server/services/mailservice"
|
||||||
"github.com/mattermost/mattermost-server/store"
|
"github.com/mattermost/mattermost-server/store"
|
||||||
|
"github.com/mattermost/mattermost-server/store/localcachelayer"
|
||||||
"github.com/mattermost/mattermost-server/store/sqlstore"
|
"github.com/mattermost/mattermost-server/store/sqlstore"
|
||||||
"github.com/mattermost/mattermost-server/utils"
|
"github.com/mattermost/mattermost-server/utils"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@@ -61,7 +62,7 @@ func (s *Server) RunOldAppInitalization() error {
|
|||||||
|
|
||||||
if s.FakeApp().Srv.newStore == nil {
|
if s.FakeApp().Srv.newStore == nil {
|
||||||
s.FakeApp().Srv.newStore = func() store.Store {
|
s.FakeApp().Srv.newStore = func() store.Store {
|
||||||
return store.NewTimerLayer(store.NewLayeredStore(sqlstore.NewSqlSupplier(s.FakeApp().Config().SqlSettings, s.Metrics), s.Metrics, s.Cluster), s.Metrics)
|
return store.NewTimerLayer(localcachelayer.NewLocalCacheLayer(store.NewLayeredStore(sqlstore.NewSqlSupplier(s.FakeApp().Config().SqlSettings, s.Metrics), s.Metrics, s.Cluster), s.Metrics, s.Cluster), s.Metrics)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ type LayeredStoreDatabaseLayer interface {
|
|||||||
|
|
||||||
type LayeredStore struct {
|
type LayeredStore struct {
|
||||||
TmpContext context.Context
|
TmpContext context.Context
|
||||||
ReactionStore ReactionStore
|
|
||||||
RoleStore RoleStore
|
RoleStore RoleStore
|
||||||
SchemeStore SchemeStore
|
SchemeStore SchemeStore
|
||||||
DatabaseLayer LayeredStoreDatabaseLayer
|
DatabaseLayer LayeredStoreDatabaseLayer
|
||||||
@@ -38,7 +37,6 @@ func NewLayeredStore(db LayeredStoreDatabaseLayer, metrics einterfaces.MetricsIn
|
|||||||
LocalCacheLayer: NewLocalCacheSupplier(metrics, cluster),
|
LocalCacheLayer: NewLocalCacheSupplier(metrics, cluster),
|
||||||
}
|
}
|
||||||
|
|
||||||
store.ReactionStore = &LayeredReactionStore{store}
|
|
||||||
store.RoleStore = &LayeredRoleStore{store}
|
store.RoleStore = &LayeredRoleStore{store}
|
||||||
store.SchemeStore = &LayeredSchemeStore{store}
|
store.SchemeStore = &LayeredSchemeStore{store}
|
||||||
|
|
||||||
@@ -143,7 +141,7 @@ func (s *LayeredStore) FileInfo() FileInfoStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *LayeredStore) Reaction() ReactionStore {
|
func (s *LayeredStore) Reaction() ReactionStore {
|
||||||
return s.ReactionStore
|
return s.DatabaseLayer.Reaction()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *LayeredStore) Job() JobStore {
|
func (s *LayeredStore) Job() JobStore {
|
||||||
@@ -219,34 +217,6 @@ func (s *LayeredStore) TotalSearchDbConnections() int {
|
|||||||
return s.DatabaseLayer.TotalSearchDbConnections()
|
return s.DatabaseLayer.TotalSearchDbConnections()
|
||||||
}
|
}
|
||||||
|
|
||||||
type LayeredReactionStore struct {
|
|
||||||
*LayeredStore
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *LayeredReactionStore) Save(reaction *model.Reaction) (*model.Reaction, *model.AppError) {
|
|
||||||
return s.LayerChainHead.ReactionSave(s.TmpContext, reaction)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *LayeredReactionStore) Delete(reaction *model.Reaction) (*model.Reaction, *model.AppError) {
|
|
||||||
return s.LayerChainHead.ReactionDelete(s.TmpContext, reaction)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *LayeredReactionStore) GetForPost(postId string, allowFromCache bool) ([]*model.Reaction, *model.AppError) {
|
|
||||||
return s.LayerChainHead.ReactionGetForPost(s.TmpContext, postId)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *LayeredReactionStore) BulkGetForPosts(postIds []string) ([]*model.Reaction, *model.AppError) {
|
|
||||||
return s.LayerChainHead.ReactionsBulkGetForPosts(s.TmpContext, postIds)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *LayeredReactionStore) DeleteAllWithEmojiName(emojiName string) *model.AppError {
|
|
||||||
return s.LayerChainHead.ReactionDeleteAllWithEmojiName(s.TmpContext, emojiName)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *LayeredReactionStore) PermanentDeleteBatch(endTime int64, limit int64) (int64, *model.AppError) {
|
|
||||||
return s.LayerChainHead.ReactionPermanentDeleteBatch(s.TmpContext, endTime, limit)
|
|
||||||
}
|
|
||||||
|
|
||||||
type LayeredRoleStore struct {
|
type LayeredRoleStore struct {
|
||||||
*LayeredStore
|
*LayeredStore
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,16 +21,6 @@ type LayeredStoreSupplier interface {
|
|||||||
SetChainNext(LayeredStoreSupplier)
|
SetChainNext(LayeredStoreSupplier)
|
||||||
Next() LayeredStoreSupplier
|
Next() LayeredStoreSupplier
|
||||||
|
|
||||||
//
|
|
||||||
// Reactions
|
|
||||||
//), hints ...LayeredStoreHint)
|
|
||||||
ReactionSave(ctx context.Context, reaction *model.Reaction, hints ...LayeredStoreHint) (*model.Reaction, *model.AppError)
|
|
||||||
ReactionDelete(ctx context.Context, reaction *model.Reaction, hints ...LayeredStoreHint) (*model.Reaction, *model.AppError)
|
|
||||||
ReactionGetForPost(ctx context.Context, postId string, hints ...LayeredStoreHint) ([]*model.Reaction, *model.AppError)
|
|
||||||
ReactionDeleteAllWithEmojiName(ctx context.Context, emojiName string, hints ...LayeredStoreHint) *model.AppError
|
|
||||||
ReactionPermanentDeleteBatch(ctx context.Context, endTime int64, limit int64, hints ...LayeredStoreHint) (int64, *model.AppError)
|
|
||||||
ReactionsBulkGetForPosts(ctx context.Context, postIds []string, hints ...LayeredStoreHint) ([]*model.Reaction, *model.AppError)
|
|
||||||
|
|
||||||
// Roles
|
// Roles
|
||||||
RoleSave(ctx context.Context, role *model.Role, hints ...LayeredStoreHint) (*model.Role, *model.AppError)
|
RoleSave(ctx context.Context, role *model.Role, hints ...LayeredStoreHint) (*model.Role, *model.AppError)
|
||||||
RoleGet(ctx context.Context, roleId string, hints ...LayeredStoreHint) (*model.Role, *model.AppError)
|
RoleGet(ctx context.Context, roleId string, hints ...LayeredStoreHint) (*model.Role, *model.AppError)
|
||||||
|
|||||||
@@ -12,9 +12,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
REACTION_CACHE_SIZE = 20000
|
|
||||||
REACTION_CACHE_SEC = 30 * 60
|
|
||||||
|
|
||||||
ROLE_CACHE_SIZE = 20000
|
ROLE_CACHE_SIZE = 20000
|
||||||
ROLE_CACHE_SEC = 30 * 60
|
ROLE_CACHE_SEC = 30 * 60
|
||||||
|
|
||||||
@@ -29,7 +26,6 @@ const (
|
|||||||
|
|
||||||
type LocalCacheSupplier struct {
|
type LocalCacheSupplier struct {
|
||||||
next LayeredStoreSupplier
|
next LayeredStoreSupplier
|
||||||
reactionCache *utils.Cache
|
|
||||||
roleCache *utils.Cache
|
roleCache *utils.Cache
|
||||||
schemeCache *utils.Cache
|
schemeCache *utils.Cache
|
||||||
metrics einterfaces.MetricsInterface
|
metrics einterfaces.MetricsInterface
|
||||||
@@ -50,7 +46,6 @@ type ObjectCache interface {
|
|||||||
|
|
||||||
func NewLocalCacheSupplier(metrics einterfaces.MetricsInterface, cluster einterfaces.ClusterInterface) *LocalCacheSupplier {
|
func NewLocalCacheSupplier(metrics einterfaces.MetricsInterface, cluster einterfaces.ClusterInterface) *LocalCacheSupplier {
|
||||||
supplier := &LocalCacheSupplier{
|
supplier := &LocalCacheSupplier{
|
||||||
reactionCache: utils.NewLruWithParams(REACTION_CACHE_SIZE, "Reaction", REACTION_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_REACTIONS),
|
|
||||||
roleCache: utils.NewLruWithParams(ROLE_CACHE_SIZE, "Role", ROLE_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_ROLES),
|
roleCache: utils.NewLruWithParams(ROLE_CACHE_SIZE, "Role", ROLE_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_ROLES),
|
||||||
schemeCache: utils.NewLruWithParams(SCHEME_CACHE_SIZE, "Scheme", SCHEME_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_SCHEMES),
|
schemeCache: utils.NewLruWithParams(SCHEME_CACHE_SIZE, "Scheme", SCHEME_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_SCHEMES),
|
||||||
metrics: metrics,
|
metrics: metrics,
|
||||||
@@ -58,7 +53,6 @@ func NewLocalCacheSupplier(metrics einterfaces.MetricsInterface, cluster einterf
|
|||||||
}
|
}
|
||||||
|
|
||||||
if cluster != nil {
|
if cluster != nil {
|
||||||
cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_REACTIONS, supplier.handleClusterInvalidateReaction)
|
|
||||||
cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_ROLES, supplier.handleClusterInvalidateRole)
|
cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_ROLES, supplier.handleClusterInvalidateRole)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,7 +122,6 @@ func (s *LocalCacheSupplier) doClearCacheCluster(cache ObjectCache) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *LocalCacheSupplier) Invalidate() {
|
func (s *LocalCacheSupplier) Invalidate() {
|
||||||
s.doClearCacheCluster(s.reactionCache)
|
|
||||||
s.doClearCacheCluster(s.roleCache)
|
s.doClearCacheCluster(s.roleCache)
|
||||||
s.doClearCacheCluster(s.schemeCache)
|
s.doClearCacheCluster(s.schemeCache)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
|
||||||
// See License.txt for license information.
|
|
||||||
|
|
||||||
package store
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/mattermost/mattermost-server/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (s *LocalCacheSupplier) handleClusterInvalidateReaction(msg *model.ClusterMessage) {
|
|
||||||
if msg.Data == CLEAR_CACHE_MESSAGE_DATA {
|
|
||||||
s.reactionCache.Purge()
|
|
||||||
} else {
|
|
||||||
s.reactionCache.Remove(msg.Data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *LocalCacheSupplier) ReactionSave(ctx context.Context, reaction *model.Reaction, hints ...LayeredStoreHint) (*model.Reaction, *model.AppError) {
|
|
||||||
defer s.doInvalidateCacheCluster(s.reactionCache, reaction.PostId)
|
|
||||||
return s.Next().ReactionSave(ctx, reaction, hints...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *LocalCacheSupplier) ReactionDelete(ctx context.Context, reaction *model.Reaction, hints ...LayeredStoreHint) (*model.Reaction, *model.AppError) {
|
|
||||||
defer s.doInvalidateCacheCluster(s.reactionCache, reaction.PostId)
|
|
||||||
return s.Next().ReactionDelete(ctx, reaction, hints...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *LocalCacheSupplier) ReactionGetForPost(ctx context.Context, postId string, hints ...LayeredStoreHint) ([]*model.Reaction, *model.AppError) {
|
|
||||||
if result := s.doStandardReadCache(ctx, s.reactionCache, postId, hints...); result != nil {
|
|
||||||
return result.Data.([]*model.Reaction), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
reaction, err := s.Next().ReactionGetForPost(ctx, postId, hints...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
result := NewSupplierResult()
|
|
||||||
result.Data = reaction
|
|
||||||
s.doStandardAddToCache(ctx, s.reactionCache, postId, result, hints...)
|
|
||||||
|
|
||||||
return reaction, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *LocalCacheSupplier) ReactionDeleteAllWithEmojiName(ctx context.Context, emojiName string, hints ...LayeredStoreHint) *model.AppError {
|
|
||||||
// This could be improved. Right now we just clear the whole
|
|
||||||
// cache because we don't have a way find what post Ids have this emoji name.
|
|
||||||
defer s.doClearCacheCluster(s.reactionCache)
|
|
||||||
return s.Next().ReactionDeleteAllWithEmojiName(ctx, emojiName, hints...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *LocalCacheSupplier) ReactionPermanentDeleteBatch(ctx context.Context, endTime int64, limit int64, hints ...LayeredStoreHint) (int64, *model.AppError) {
|
|
||||||
// Don't bother to clear the cache as the posts will be gone anyway and the reactions being deleted will
|
|
||||||
// expire from the cache in due course.
|
|
||||||
return s.Next().ReactionPermanentDeleteBatch(ctx, endTime, limit)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *LocalCacheSupplier) ReactionsBulkGetForPosts(ctx context.Context, postIds []string, hints ...LayeredStoreHint) ([]*model.Reaction, *model.AppError) {
|
|
||||||
// Ignoring this.
|
|
||||||
return s.Next().ReactionsBulkGetForPosts(ctx, postIds, hints...)
|
|
||||||
}
|
|
||||||
97
store/localcachelayer/layer.go
Обычный файл
97
store/localcachelayer/layer.go
Обычный файл
@@ -0,0 +1,97 @@
|
|||||||
|
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See License.txt for license information.
|
||||||
|
|
||||||
|
package localcachelayer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/mattermost/mattermost-server/einterfaces"
|
||||||
|
"github.com/mattermost/mattermost-server/model"
|
||||||
|
"github.com/mattermost/mattermost-server/store"
|
||||||
|
"github.com/mattermost/mattermost-server/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
REACTION_CACHE_SIZE = 20000
|
||||||
|
REACTION_CACHE_SEC = 30 * 60
|
||||||
|
|
||||||
|
CLEAR_CACHE_MESSAGE_DATA = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
type LocalCacheStore struct {
|
||||||
|
store.Store
|
||||||
|
metrics einterfaces.MetricsInterface
|
||||||
|
cluster einterfaces.ClusterInterface
|
||||||
|
reaction LocalCacheReactionStore
|
||||||
|
reactionCache *utils.Cache
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLocalCacheLayer(baseStore store.Store, metrics einterfaces.MetricsInterface, cluster einterfaces.ClusterInterface) LocalCacheStore {
|
||||||
|
localCacheStore := LocalCacheStore{
|
||||||
|
Store: baseStore,
|
||||||
|
cluster: cluster,
|
||||||
|
metrics: metrics,
|
||||||
|
}
|
||||||
|
localCacheStore.reactionCache = utils.NewLruWithParams(REACTION_CACHE_SIZE, "Reaction", REACTION_CACHE_SEC, model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_REACTIONS)
|
||||||
|
localCacheStore.reaction = LocalCacheReactionStore{ReactionStore: baseStore.Reaction(), rootStore: &localCacheStore}
|
||||||
|
|
||||||
|
if cluster != nil {
|
||||||
|
cluster.RegisterClusterMessageHandler(model.CLUSTER_EVENT_INVALIDATE_CACHE_FOR_REACTIONS, localCacheStore.reaction.handleClusterInvalidateReaction)
|
||||||
|
}
|
||||||
|
return localCacheStore
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s LocalCacheStore) Reaction() store.ReactionStore {
|
||||||
|
return s.reaction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s LocalCacheStore) DropAllTables() {
|
||||||
|
s.Invalidate()
|
||||||
|
s.Store.DropAllTables()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LocalCacheStore) doInvalidateCacheCluster(cache *utils.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 *utils.Cache, key string, value interface{}) {
|
||||||
|
cache.AddWithDefaultExpires(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LocalCacheStore) doStandardReadCache(cache *utils.Cache, key string) interface{} {
|
||||||
|
if cacheItem, ok := cache.Get(key); ok {
|
||||||
|
if s.metrics != nil {
|
||||||
|
s.metrics.IncrementMemCacheHitCounter(cache.Name())
|
||||||
|
}
|
||||||
|
return cacheItem
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.metrics != nil {
|
||||||
|
s.metrics.IncrementMemCacheMissCounter(cache.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LocalCacheStore) doClearCacheCluster(cache *utils.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)
|
||||||
|
}
|
||||||
99
store/localcachelayer/layer_test.go
Обычный файл
99
store/localcachelayer/layer_test.go
Обычный файл
@@ -0,0 +1,99 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See License.txt for license information.
|
||||||
|
|
||||||
|
package localcachelayer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/mattermost/mattermost-server/model"
|
||||||
|
"github.com/mattermost/mattermost-server/store"
|
||||||
|
"github.com/mattermost/mattermost-server/store/sqlstore"
|
||||||
|
"github.com/mattermost/mattermost-server/store/storetest"
|
||||||
|
)
|
||||||
|
|
||||||
|
type storeType struct {
|
||||||
|
Name string
|
||||||
|
SqlSettings *model.SqlSettings
|
||||||
|
SqlSupplier *sqlstore.SqlSupplier
|
||||||
|
Store store.Store
|
||||||
|
}
|
||||||
|
|
||||||
|
var storeTypes []*storeType
|
||||||
|
|
||||||
|
func StoreTest(t *testing.T, f func(*testing.T, store.Store)) {
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
tearDownStores()
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
for _, st := range storeTypes {
|
||||||
|
st := st
|
||||||
|
t.Run(st.Name, func(t *testing.T) { f(t, st.Store) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func StoreTestWithSqlSupplier(t *testing.T, f func(*testing.T, store.Store, storetest.SqlSupplier)) {
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
tearDownStores()
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
for _, st := range storeTypes {
|
||||||
|
st := st
|
||||||
|
t.Run(st.Name, func(t *testing.T) { f(t, st.Store, st.SqlSupplier) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func initStores() {
|
||||||
|
storeTypes = append(storeTypes, &storeType{
|
||||||
|
Name: "LocalCache+MySQL",
|
||||||
|
SqlSettings: storetest.MakeSqlSettings(model.DATABASE_DRIVER_MYSQL),
|
||||||
|
})
|
||||||
|
storeTypes = append(storeTypes, &storeType{
|
||||||
|
Name: "LocalCache+PostgreSQL",
|
||||||
|
SqlSettings: storetest.MakeSqlSettings(model.DATABASE_DRIVER_POSTGRES),
|
||||||
|
})
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
tearDownStores()
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for _, st := range storeTypes {
|
||||||
|
st := st
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
st.SqlSupplier = sqlstore.NewSqlSupplier(*st.SqlSettings, nil)
|
||||||
|
st.Store = NewLocalCacheLayer(store.NewLayeredStore(st.SqlSupplier, nil, nil), nil, nil)
|
||||||
|
st.Store.DropAllTables()
|
||||||
|
st.Store.MarkSystemRanUnitTests()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
var tearDownStoresOnce sync.Once
|
||||||
|
|
||||||
|
func tearDownStores() {
|
||||||
|
tearDownStoresOnce.Do(func() {
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(len(storeTypes))
|
||||||
|
for _, st := range storeTypes {
|
||||||
|
st := st
|
||||||
|
go func() {
|
||||||
|
if st.Store != nil {
|
||||||
|
st.Store.Close()
|
||||||
|
}
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
})
|
||||||
|
}
|
||||||
21
store/localcachelayer/main_test.go
Обычный файл
21
store/localcachelayer/main_test.go
Обычный файл
@@ -0,0 +1,21 @@
|
|||||||
|
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See License.txt for license information.
|
||||||
|
|
||||||
|
package localcachelayer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/mattermost/mattermost-server/testlib"
|
||||||
|
)
|
||||||
|
|
||||||
|
var mainHelper *testlib.MainHelper
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
mainHelper = testlib.NewMainHelperWithOptions(nil)
|
||||||
|
defer mainHelper.Close()
|
||||||
|
|
||||||
|
initStores()
|
||||||
|
mainHelper.Main(m)
|
||||||
|
tearDownStores()
|
||||||
|
}
|
||||||
58
store/localcachelayer/reaction_layer.go
Обычный файл
58
store/localcachelayer/reaction_layer.go
Обычный файл
@@ -0,0 +1,58 @@
|
|||||||
|
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See License.txt for license information.
|
||||||
|
|
||||||
|
package localcachelayer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/mattermost/mattermost-server/model"
|
||||||
|
"github.com/mattermost/mattermost-server/store"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LocalCacheReactionStore struct {
|
||||||
|
store.ReactionStore
|
||||||
|
rootStore *LocalCacheStore
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LocalCacheReactionStore) handleClusterInvalidateReaction(msg *model.ClusterMessage) {
|
||||||
|
if msg.Data == CLEAR_CACHE_MESSAGE_DATA {
|
||||||
|
s.rootStore.reactionCache.Purge()
|
||||||
|
} else {
|
||||||
|
s.rootStore.reactionCache.Remove(msg.Data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s LocalCacheReactionStore) Save(reaction *model.Reaction) (*model.Reaction, *model.AppError) {
|
||||||
|
defer s.rootStore.doInvalidateCacheCluster(s.rootStore.reactionCache, reaction.PostId)
|
||||||
|
return s.ReactionStore.Save(reaction)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s LocalCacheReactionStore) Delete(reaction *model.Reaction) (*model.Reaction, *model.AppError) {
|
||||||
|
defer s.rootStore.doInvalidateCacheCluster(s.rootStore.reactionCache, reaction.PostId)
|
||||||
|
return s.ReactionStore.Delete(reaction)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s LocalCacheReactionStore) GetForPost(postId string, allowFromCache bool) ([]*model.Reaction, *model.AppError) {
|
||||||
|
if !allowFromCache {
|
||||||
|
return s.ReactionStore.GetForPost(postId, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if reaction := s.rootStore.doStandardReadCache(s.rootStore.reactionCache, postId); reaction != nil {
|
||||||
|
return reaction.([]*model.Reaction), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
reaction, err := s.ReactionStore.GetForPost(postId, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
s.rootStore.doStandardAddToCache(s.rootStore.reactionCache, postId, reaction)
|
||||||
|
|
||||||
|
return reaction, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s LocalCacheReactionStore) DeleteAllWithEmojiName(emojiName string) *model.AppError {
|
||||||
|
// This could be improved. Right now we just clear the whole
|
||||||
|
// cache because we don't have a way find what post Ids have this emoji name.
|
||||||
|
defer s.rootStore.doClearCacheCluster(s.rootStore.reactionCache)
|
||||||
|
return s.ReactionStore.DeleteAllWithEmojiName(emojiName)
|
||||||
|
}
|
||||||
92
store/localcachelayer/reaction_layer_test.go
Обычный файл
92
store/localcachelayer/reaction_layer_test.go
Обычный файл
@@ -0,0 +1,92 @@
|
|||||||
|
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See License.txt for license information.
|
||||||
|
|
||||||
|
package localcachelayer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/mattermost/mattermost-server/model"
|
||||||
|
"github.com/mattermost/mattermost-server/store/storetest"
|
||||||
|
"github.com/mattermost/mattermost-server/store/storetest/mocks"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestReactionStore(t *testing.T) {
|
||||||
|
StoreTest(t, storetest.TestReactionStore)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReactionStoreCache(t *testing.T) {
|
||||||
|
fakeReaction := model.Reaction{PostId: "123"}
|
||||||
|
|
||||||
|
t.Run("first call not cached, second cached and returning same data", func(t *testing.T) {
|
||||||
|
mockStore := mocks.Store{}
|
||||||
|
mockReactionsStore := mocks.ReactionStore{}
|
||||||
|
mockReactionsStore.On("Save", &fakeReaction).Return(&model.Reaction{}, nil)
|
||||||
|
mockReactionsStore.On("Delete", &fakeReaction).Return(&model.Reaction{}, nil)
|
||||||
|
mockReactionsStore.On("GetForPost", "123", false).Return([]*model.Reaction{&fakeReaction}, nil)
|
||||||
|
mockReactionsStore.On("GetForPost", "123", true).Return([]*model.Reaction{&fakeReaction}, nil)
|
||||||
|
mockStore.On("Reaction").Return(&mockReactionsStore)
|
||||||
|
cachedStore := NewLocalCacheLayer(&mockStore, nil, nil)
|
||||||
|
|
||||||
|
reaction, err := cachedStore.Reaction().GetForPost("123", true)
|
||||||
|
require.Nil(t, err)
|
||||||
|
assert.Equal(t, reaction, []*model.Reaction{&fakeReaction})
|
||||||
|
mockReactionsStore.AssertNumberOfCalls(t, "GetForPost", 1)
|
||||||
|
require.Nil(t, err)
|
||||||
|
assert.Equal(t, reaction, []*model.Reaction{&fakeReaction})
|
||||||
|
cachedStore.Reaction().GetForPost("123", true)
|
||||||
|
mockReactionsStore.AssertNumberOfCalls(t, "GetForPost", 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("first call not cached, second force no cached", func(t *testing.T) {
|
||||||
|
mockStore := mocks.Store{}
|
||||||
|
mockReactionsStore := mocks.ReactionStore{}
|
||||||
|
mockReactionsStore.On("Save", &fakeReaction).Return(&model.Reaction{}, nil)
|
||||||
|
mockReactionsStore.On("Delete", &fakeReaction).Return(&model.Reaction{}, nil)
|
||||||
|
mockReactionsStore.On("GetForPost", "123", false).Return([]*model.Reaction{&fakeReaction}, nil)
|
||||||
|
mockReactionsStore.On("GetForPost", "123", true).Return([]*model.Reaction{&fakeReaction}, nil)
|
||||||
|
mockStore.On("Reaction").Return(&mockReactionsStore)
|
||||||
|
cachedStore := NewLocalCacheLayer(&mockStore, nil, nil)
|
||||||
|
|
||||||
|
cachedStore.Reaction().GetForPost("123", true)
|
||||||
|
mockReactionsStore.AssertNumberOfCalls(t, "GetForPost", 1)
|
||||||
|
cachedStore.Reaction().GetForPost("123", false)
|
||||||
|
mockReactionsStore.AssertNumberOfCalls(t, "GetForPost", 2)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("first call not cached, save, and then not cached again", func(t *testing.T) {
|
||||||
|
mockStore := mocks.Store{}
|
||||||
|
mockReactionsStore := mocks.ReactionStore{}
|
||||||
|
mockReactionsStore.On("Save", &fakeReaction).Return(&model.Reaction{}, nil)
|
||||||
|
mockReactionsStore.On("Delete", &fakeReaction).Return(&model.Reaction{}, nil)
|
||||||
|
mockReactionsStore.On("GetForPost", "123", false).Return([]*model.Reaction{&fakeReaction}, nil)
|
||||||
|
mockReactionsStore.On("GetForPost", "123", true).Return([]*model.Reaction{&fakeReaction}, nil)
|
||||||
|
mockStore.On("Reaction").Return(&mockReactionsStore)
|
||||||
|
cachedStore := NewLocalCacheLayer(&mockStore, nil, nil)
|
||||||
|
|
||||||
|
cachedStore.Reaction().GetForPost("123", true)
|
||||||
|
mockReactionsStore.AssertNumberOfCalls(t, "GetForPost", 1)
|
||||||
|
cachedStore.Reaction().Save(&fakeReaction)
|
||||||
|
cachedStore.Reaction().GetForPost("123", true)
|
||||||
|
mockReactionsStore.AssertNumberOfCalls(t, "GetForPost", 2)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("first call not cached, delete, and then not cached again", func(t *testing.T) {
|
||||||
|
mockStore := mocks.Store{}
|
||||||
|
mockReactionsStore := mocks.ReactionStore{}
|
||||||
|
mockReactionsStore.On("Save", &fakeReaction).Return(&model.Reaction{}, nil)
|
||||||
|
mockReactionsStore.On("Delete", &fakeReaction).Return(&model.Reaction{}, nil)
|
||||||
|
mockReactionsStore.On("GetForPost", "123", false).Return([]*model.Reaction{&fakeReaction}, nil)
|
||||||
|
mockReactionsStore.On("GetForPost", "123", true).Return([]*model.Reaction{&fakeReaction}, nil)
|
||||||
|
mockStore.On("Reaction").Return(&mockReactionsStore)
|
||||||
|
cachedStore := NewLocalCacheLayer(&mockStore, nil, nil)
|
||||||
|
|
||||||
|
cachedStore.Reaction().GetForPost("123", true)
|
||||||
|
mockReactionsStore.AssertNumberOfCalls(t, "GetForPost", 1)
|
||||||
|
cachedStore.Reaction().Delete(&fakeReaction)
|
||||||
|
cachedStore.Reaction().GetForPost("123", true)
|
||||||
|
mockReactionsStore.AssertNumberOfCalls(t, "GetForPost", 2)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
|
||||||
// See License.txt for license information.
|
|
||||||
|
|
||||||
package store
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/mattermost/mattermost-server/mlog"
|
|
||||||
"github.com/mattermost/mattermost-server/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (s *RedisSupplier) ReactionSave(ctx context.Context, reaction *model.Reaction, hints ...LayeredStoreHint) (*model.Reaction, *model.AppError) {
|
|
||||||
if err := s.client.Del("reactions:" + reaction.PostId).Err(); err != nil {
|
|
||||||
mlog.Error("Redis failed to remove key reactions:" + reaction.PostId + " Error: " + err.Error())
|
|
||||||
}
|
|
||||||
return s.Next().ReactionSave(ctx, reaction, hints...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *RedisSupplier) ReactionDelete(ctx context.Context, reaction *model.Reaction, hints ...LayeredStoreHint) (*model.Reaction, *model.AppError) {
|
|
||||||
if err := s.client.Del("reactions:" + reaction.PostId).Err(); err != nil {
|
|
||||||
mlog.Error("Redis failed to remove key reactions:" + reaction.PostId + " Error: " + err.Error())
|
|
||||||
}
|
|
||||||
return s.Next().ReactionDelete(ctx, reaction, hints...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *RedisSupplier) ReactionGetForPost(ctx context.Context, postId string, hints ...LayeredStoreHint) ([]*model.Reaction, *model.AppError) {
|
|
||||||
var reaction []*model.Reaction
|
|
||||||
found, err := s.load("reactions:"+postId, &reaction)
|
|
||||||
if found {
|
|
||||||
return reaction, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
mlog.Error("Redis encountered an error on read: " + err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
reaction, appErr := s.Next().ReactionGetForPost(ctx, postId, hints...)
|
|
||||||
if appErr != nil {
|
|
||||||
return nil, appErr
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := s.save("reactions:"+postId, reaction, REDIS_EXPIRY_TIME); err != nil {
|
|
||||||
mlog.Error("Redis encountered and error on write: " + err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return reaction, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *RedisSupplier) ReactionDeleteAllWithEmojiName(ctx context.Context, emojiName string, hints ...LayeredStoreHint) *model.AppError {
|
|
||||||
// Ignoring this. It's probably OK to have the emoji slowly expire from Redis.
|
|
||||||
return s.Next().ReactionDeleteAllWithEmojiName(ctx, emojiName, hints...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *RedisSupplier) ReactionPermanentDeleteBatch(ctx context.Context, endTime int64, limit int64, hints ...LayeredStoreHint) (int64, *model.AppError) {
|
|
||||||
// Ignoring this. It's probably OK to have the emoji slowly expire from Redis.
|
|
||||||
return s.Next().ReactionPermanentDeleteBatch(ctx, endTime, limit, hints...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *RedisSupplier) ReactionsBulkGetForPosts(ctx context.Context, postIds []string, hints ...LayeredStoreHint) ([]*model.Reaction, *model.AppError) {
|
|
||||||
// Ignoring this.
|
|
||||||
return s.Next().ReactionsBulkGetForPosts(ctx, postIds, hints...)
|
|
||||||
}
|
|
||||||
@@ -151,9 +151,9 @@ func NewSqlSupplier(settings model.SqlSettings, metrics einterfaces.MetricsInter
|
|||||||
supplier.oldStores.TermsOfService = NewSqlTermsOfServiceStore(supplier, metrics)
|
supplier.oldStores.TermsOfService = NewSqlTermsOfServiceStore(supplier, metrics)
|
||||||
supplier.oldStores.UserTermsOfService = NewSqlUserTermsOfServiceStore(supplier)
|
supplier.oldStores.UserTermsOfService = NewSqlUserTermsOfServiceStore(supplier)
|
||||||
supplier.oldStores.linkMetadata = NewSqlLinkMetadataStore(supplier)
|
supplier.oldStores.linkMetadata = NewSqlLinkMetadataStore(supplier)
|
||||||
|
supplier.oldStores.reaction = NewSqlReactionStore(supplier)
|
||||||
supplier.oldStores.group = NewSqlGroupStore(supplier)
|
supplier.oldStores.group = NewSqlGroupStore(supplier)
|
||||||
|
|
||||||
initSqlSupplierReactions(supplier)
|
|
||||||
initSqlSupplierRoles(supplier)
|
initSqlSupplierRoles(supplier)
|
||||||
initSqlSupplierSchemes(supplier)
|
initSqlSupplierSchemes(supplier)
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
package sqlstore
|
package sqlstore
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
@@ -14,16 +13,27 @@ import (
|
|||||||
"github.com/mattermost/mattermost-server/store"
|
"github.com/mattermost/mattermost-server/store"
|
||||||
)
|
)
|
||||||
|
|
||||||
func initSqlSupplierReactions(sqlStore SqlStore) {
|
type SqlReactionStore struct {
|
||||||
|
SqlStore
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSqlReactionStore(sqlStore SqlStore) store.ReactionStore {
|
||||||
|
s := &SqlReactionStore{sqlStore}
|
||||||
|
|
||||||
for _, db := range sqlStore.GetAllConns() {
|
for _, db := range sqlStore.GetAllConns() {
|
||||||
table := db.AddTableWithName(model.Reaction{}, "Reactions").SetKeys(false, "UserId", "PostId", "EmojiName")
|
table := db.AddTableWithName(model.Reaction{}, "Reactions").SetKeys(false, "UserId", "PostId", "EmojiName")
|
||||||
table.ColMap("UserId").SetMaxSize(26)
|
table.ColMap("UserId").SetMaxSize(26)
|
||||||
table.ColMap("PostId").SetMaxSize(26)
|
table.ColMap("PostId").SetMaxSize(26)
|
||||||
table.ColMap("EmojiName").SetMaxSize(64)
|
table.ColMap("EmojiName").SetMaxSize(64)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqlSupplier) ReactionSave(ctx context.Context, reaction *model.Reaction, hints ...store.LayeredStoreHint) (*model.Reaction, *model.AppError) {
|
func (s SqlReactionStore) CreateIndexesIfNotExists() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SqlReactionStore) Save(reaction *model.Reaction) (*model.Reaction, *model.AppError) {
|
||||||
reaction.PreSave()
|
reaction.PreSave()
|
||||||
if err := reaction.IsValid(); err != nil {
|
if err := reaction.IsValid(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -49,7 +59,7 @@ func (s *SqlSupplier) ReactionSave(ctx context.Context, reaction *model.Reaction
|
|||||||
return reaction, nil
|
return reaction, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqlSupplier) ReactionDelete(ctx context.Context, reaction *model.Reaction, hints ...store.LayeredStoreHint) (*model.Reaction, *model.AppError) {
|
func (s *SqlReactionStore) Delete(reaction *model.Reaction) (*model.Reaction, *model.AppError) {
|
||||||
transaction, err := s.GetMaster().Begin()
|
transaction, err := s.GetMaster().Begin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, model.NewAppError("SqlReactionStore.Delete", "store.sql_reaction.delete.begin.app_error", nil, err.Error(), http.StatusInternalServerError)
|
return nil, model.NewAppError("SqlReactionStore.Delete", "store.sql_reaction.delete.begin.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||||
@@ -68,7 +78,7 @@ func (s *SqlSupplier) ReactionDelete(ctx context.Context, reaction *model.Reacti
|
|||||||
return reaction, nil
|
return reaction, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqlSupplier) ReactionGetForPost(ctx context.Context, postId string, hints ...store.LayeredStoreHint) ([]*model.Reaction, *model.AppError) {
|
func (s *SqlReactionStore) GetForPost(postId string, allowFromCache bool) ([]*model.Reaction, *model.AppError) {
|
||||||
var reactions []*model.Reaction
|
var reactions []*model.Reaction
|
||||||
|
|
||||||
if _, err := s.GetReplica().Select(&reactions,
|
if _, err := s.GetReplica().Select(&reactions,
|
||||||
@@ -86,7 +96,7 @@ func (s *SqlSupplier) ReactionGetForPost(ctx context.Context, postId string, hin
|
|||||||
return reactions, nil
|
return reactions, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqlSupplier) ReactionsBulkGetForPosts(ctx context.Context, postIds []string, hints ...store.LayeredStoreHint) ([]*model.Reaction, *model.AppError) {
|
func (s *SqlReactionStore) BulkGetForPosts(postIds []string) ([]*model.Reaction, *model.AppError) {
|
||||||
keys, params := MapStringsToQueryParams(postIds, "postId")
|
keys, params := MapStringsToQueryParams(postIds, "postId")
|
||||||
var reactions []*model.Reaction
|
var reactions []*model.Reaction
|
||||||
|
|
||||||
@@ -103,7 +113,7 @@ func (s *SqlSupplier) ReactionsBulkGetForPosts(ctx context.Context, postIds []st
|
|||||||
return reactions, nil
|
return reactions, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqlSupplier) ReactionDeleteAllWithEmojiName(ctx context.Context, emojiName string, hints ...store.LayeredStoreHint) *model.AppError {
|
func (s *SqlReactionStore) DeleteAllWithEmojiName(emojiName string) *model.AppError {
|
||||||
var reactions []*model.Reaction
|
var reactions []*model.Reaction
|
||||||
|
|
||||||
if _, err := s.GetReplica().Select(&reactions,
|
if _, err := s.GetReplica().Select(&reactions,
|
||||||
@@ -138,7 +148,7 @@ func (s *SqlSupplier) ReactionDeleteAllWithEmojiName(ctx context.Context, emojiN
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqlSupplier) ReactionPermanentDeleteBatch(ctx context.Context, endTime int64, limit int64, hints ...store.LayeredStoreHint) (int64, *model.AppError) {
|
func (s *SqlReactionStore) PermanentDeleteBatch(endTime int64, limit int64) (int64, *model.AppError) {
|
||||||
var query string
|
var query string
|
||||||
if s.DriverName() == "postgres" {
|
if s.DriverName() == "postgres" {
|
||||||
query = "DELETE from Reactions WHERE CreateAt = any (array (SELECT CreateAt FROM Reactions WHERE CreateAt < :EndTime LIMIT :Limit))"
|
query = "DELETE from Reactions WHERE CreateAt = any (array (SELECT CreateAt FROM Reactions WHERE CreateAt < :EndTime LIMIT :Limit))"
|
||||||
|
|||||||
@@ -368,187 +368,6 @@ func (_m *LayeredStoreDatabaseLayer) Reaction() store.ReactionStore {
|
|||||||
return r0
|
return r0
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReactionDelete provides a mock function with given fields: ctx, reaction, hints
|
|
||||||
func (_m *LayeredStoreDatabaseLayer) ReactionDelete(ctx context.Context, reaction *model.Reaction, hints ...store.LayeredStoreHint) (*model.Reaction, *model.AppError) {
|
|
||||||
_va := make([]interface{}, len(hints))
|
|
||||||
for _i := range hints {
|
|
||||||
_va[_i] = hints[_i]
|
|
||||||
}
|
|
||||||
var _ca []interface{}
|
|
||||||
_ca = append(_ca, ctx, reaction)
|
|
||||||
_ca = append(_ca, _va...)
|
|
||||||
ret := _m.Called(_ca...)
|
|
||||||
|
|
||||||
var r0 *model.Reaction
|
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, *model.Reaction, ...store.LayeredStoreHint) *model.Reaction); ok {
|
|
||||||
r0 = rf(ctx, reaction, hints...)
|
|
||||||
} else {
|
|
||||||
if ret.Get(0) != nil {
|
|
||||||
r0 = ret.Get(0).(*model.Reaction)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var r1 *model.AppError
|
|
||||||
if rf, ok := ret.Get(1).(func(context.Context, *model.Reaction, ...store.LayeredStoreHint) *model.AppError); ok {
|
|
||||||
r1 = rf(ctx, reaction, hints...)
|
|
||||||
} else {
|
|
||||||
if ret.Get(1) != nil {
|
|
||||||
r1 = ret.Get(1).(*model.AppError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return r0, r1
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReactionDeleteAllWithEmojiName provides a mock function with given fields: ctx, emojiName, hints
|
|
||||||
func (_m *LayeredStoreDatabaseLayer) ReactionDeleteAllWithEmojiName(ctx context.Context, emojiName string, hints ...store.LayeredStoreHint) *model.AppError {
|
|
||||||
_va := make([]interface{}, len(hints))
|
|
||||||
for _i := range hints {
|
|
||||||
_va[_i] = hints[_i]
|
|
||||||
}
|
|
||||||
var _ca []interface{}
|
|
||||||
_ca = append(_ca, ctx, emojiName)
|
|
||||||
_ca = append(_ca, _va...)
|
|
||||||
ret := _m.Called(_ca...)
|
|
||||||
|
|
||||||
var r0 *model.AppError
|
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, string, ...store.LayeredStoreHint) *model.AppError); ok {
|
|
||||||
r0 = rf(ctx, emojiName, hints...)
|
|
||||||
} else {
|
|
||||||
if ret.Get(0) != nil {
|
|
||||||
r0 = ret.Get(0).(*model.AppError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return r0
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReactionGetForPost provides a mock function with given fields: ctx, postId, hints
|
|
||||||
func (_m *LayeredStoreDatabaseLayer) ReactionGetForPost(ctx context.Context, postId string, hints ...store.LayeredStoreHint) ([]*model.Reaction, *model.AppError) {
|
|
||||||
_va := make([]interface{}, len(hints))
|
|
||||||
for _i := range hints {
|
|
||||||
_va[_i] = hints[_i]
|
|
||||||
}
|
|
||||||
var _ca []interface{}
|
|
||||||
_ca = append(_ca, ctx, postId)
|
|
||||||
_ca = append(_ca, _va...)
|
|
||||||
ret := _m.Called(_ca...)
|
|
||||||
|
|
||||||
var r0 []*model.Reaction
|
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, string, ...store.LayeredStoreHint) []*model.Reaction); ok {
|
|
||||||
r0 = rf(ctx, postId, hints...)
|
|
||||||
} else {
|
|
||||||
if ret.Get(0) != nil {
|
|
||||||
r0 = ret.Get(0).([]*model.Reaction)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var r1 *model.AppError
|
|
||||||
if rf, ok := ret.Get(1).(func(context.Context, string, ...store.LayeredStoreHint) *model.AppError); ok {
|
|
||||||
r1 = rf(ctx, postId, hints...)
|
|
||||||
} else {
|
|
||||||
if ret.Get(1) != nil {
|
|
||||||
r1 = ret.Get(1).(*model.AppError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return r0, r1
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReactionPermanentDeleteBatch provides a mock function with given fields: ctx, endTime, limit, hints
|
|
||||||
func (_m *LayeredStoreDatabaseLayer) ReactionPermanentDeleteBatch(ctx context.Context, endTime int64, limit int64, hints ...store.LayeredStoreHint) (int64, *model.AppError) {
|
|
||||||
_va := make([]interface{}, len(hints))
|
|
||||||
for _i := range hints {
|
|
||||||
_va[_i] = hints[_i]
|
|
||||||
}
|
|
||||||
var _ca []interface{}
|
|
||||||
_ca = append(_ca, ctx, endTime, limit)
|
|
||||||
_ca = append(_ca, _va...)
|
|
||||||
ret := _m.Called(_ca...)
|
|
||||||
|
|
||||||
var r0 int64
|
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, int64, int64, ...store.LayeredStoreHint) int64); ok {
|
|
||||||
r0 = rf(ctx, endTime, limit, hints...)
|
|
||||||
} else {
|
|
||||||
r0 = ret.Get(0).(int64)
|
|
||||||
}
|
|
||||||
|
|
||||||
var r1 *model.AppError
|
|
||||||
if rf, ok := ret.Get(1).(func(context.Context, int64, int64, ...store.LayeredStoreHint) *model.AppError); ok {
|
|
||||||
r1 = rf(ctx, endTime, limit, hints...)
|
|
||||||
} else {
|
|
||||||
if ret.Get(1) != nil {
|
|
||||||
r1 = ret.Get(1).(*model.AppError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return r0, r1
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReactionSave provides a mock function with given fields: ctx, reaction, hints
|
|
||||||
func (_m *LayeredStoreDatabaseLayer) ReactionSave(ctx context.Context, reaction *model.Reaction, hints ...store.LayeredStoreHint) (*model.Reaction, *model.AppError) {
|
|
||||||
_va := make([]interface{}, len(hints))
|
|
||||||
for _i := range hints {
|
|
||||||
_va[_i] = hints[_i]
|
|
||||||
}
|
|
||||||
var _ca []interface{}
|
|
||||||
_ca = append(_ca, ctx, reaction)
|
|
||||||
_ca = append(_ca, _va...)
|
|
||||||
ret := _m.Called(_ca...)
|
|
||||||
|
|
||||||
var r0 *model.Reaction
|
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, *model.Reaction, ...store.LayeredStoreHint) *model.Reaction); ok {
|
|
||||||
r0 = rf(ctx, reaction, hints...)
|
|
||||||
} else {
|
|
||||||
if ret.Get(0) != nil {
|
|
||||||
r0 = ret.Get(0).(*model.Reaction)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var r1 *model.AppError
|
|
||||||
if rf, ok := ret.Get(1).(func(context.Context, *model.Reaction, ...store.LayeredStoreHint) *model.AppError); ok {
|
|
||||||
r1 = rf(ctx, reaction, hints...)
|
|
||||||
} else {
|
|
||||||
if ret.Get(1) != nil {
|
|
||||||
r1 = ret.Get(1).(*model.AppError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return r0, r1
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReactionsBulkGetForPosts provides a mock function with given fields: ctx, postIds, hints
|
|
||||||
func (_m *LayeredStoreDatabaseLayer) ReactionsBulkGetForPosts(ctx context.Context, postIds []string, hints ...store.LayeredStoreHint) ([]*model.Reaction, *model.AppError) {
|
|
||||||
_va := make([]interface{}, len(hints))
|
|
||||||
for _i := range hints {
|
|
||||||
_va[_i] = hints[_i]
|
|
||||||
}
|
|
||||||
var _ca []interface{}
|
|
||||||
_ca = append(_ca, ctx, postIds)
|
|
||||||
_ca = append(_ca, _va...)
|
|
||||||
ret := _m.Called(_ca...)
|
|
||||||
|
|
||||||
var r0 []*model.Reaction
|
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, []string, ...store.LayeredStoreHint) []*model.Reaction); ok {
|
|
||||||
r0 = rf(ctx, postIds, hints...)
|
|
||||||
} else {
|
|
||||||
if ret.Get(0) != nil {
|
|
||||||
r0 = ret.Get(0).([]*model.Reaction)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var r1 *model.AppError
|
|
||||||
if rf, ok := ret.Get(1).(func(context.Context, []string, ...store.LayeredStoreHint) *model.AppError); ok {
|
|
||||||
r1 = rf(ctx, postIds, hints...)
|
|
||||||
} else {
|
|
||||||
if ret.Get(1) != nil {
|
|
||||||
r1 = ret.Get(1).(*model.AppError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return r0, r1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Role provides a mock function with given fields:
|
// Role provides a mock function with given fields:
|
||||||
func (_m *LayeredStoreDatabaseLayer) Role() store.RoleStore {
|
func (_m *LayeredStoreDatabaseLayer) Role() store.RoleStore {
|
||||||
ret := _m.Called()
|
ret := _m.Called()
|
||||||
|
|||||||
@@ -30,187 +30,6 @@ func (_m *LayeredStoreSupplier) Next() store.LayeredStoreSupplier {
|
|||||||
return r0
|
return r0
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReactionDelete provides a mock function with given fields: ctx, reaction, hints
|
|
||||||
func (_m *LayeredStoreSupplier) ReactionDelete(ctx context.Context, reaction *model.Reaction, hints ...store.LayeredStoreHint) (*model.Reaction, *model.AppError) {
|
|
||||||
_va := make([]interface{}, len(hints))
|
|
||||||
for _i := range hints {
|
|
||||||
_va[_i] = hints[_i]
|
|
||||||
}
|
|
||||||
var _ca []interface{}
|
|
||||||
_ca = append(_ca, ctx, reaction)
|
|
||||||
_ca = append(_ca, _va...)
|
|
||||||
ret := _m.Called(_ca...)
|
|
||||||
|
|
||||||
var r0 *model.Reaction
|
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, *model.Reaction, ...store.LayeredStoreHint) *model.Reaction); ok {
|
|
||||||
r0 = rf(ctx, reaction, hints...)
|
|
||||||
} else {
|
|
||||||
if ret.Get(0) != nil {
|
|
||||||
r0 = ret.Get(0).(*model.Reaction)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var r1 *model.AppError
|
|
||||||
if rf, ok := ret.Get(1).(func(context.Context, *model.Reaction, ...store.LayeredStoreHint) *model.AppError); ok {
|
|
||||||
r1 = rf(ctx, reaction, hints...)
|
|
||||||
} else {
|
|
||||||
if ret.Get(1) != nil {
|
|
||||||
r1 = ret.Get(1).(*model.AppError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return r0, r1
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReactionDeleteAllWithEmojiName provides a mock function with given fields: ctx, emojiName, hints
|
|
||||||
func (_m *LayeredStoreSupplier) ReactionDeleteAllWithEmojiName(ctx context.Context, emojiName string, hints ...store.LayeredStoreHint) *model.AppError {
|
|
||||||
_va := make([]interface{}, len(hints))
|
|
||||||
for _i := range hints {
|
|
||||||
_va[_i] = hints[_i]
|
|
||||||
}
|
|
||||||
var _ca []interface{}
|
|
||||||
_ca = append(_ca, ctx, emojiName)
|
|
||||||
_ca = append(_ca, _va...)
|
|
||||||
ret := _m.Called(_ca...)
|
|
||||||
|
|
||||||
var r0 *model.AppError
|
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, string, ...store.LayeredStoreHint) *model.AppError); ok {
|
|
||||||
r0 = rf(ctx, emojiName, hints...)
|
|
||||||
} else {
|
|
||||||
if ret.Get(0) != nil {
|
|
||||||
r0 = ret.Get(0).(*model.AppError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return r0
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReactionGetForPost provides a mock function with given fields: ctx, postId, hints
|
|
||||||
func (_m *LayeredStoreSupplier) ReactionGetForPost(ctx context.Context, postId string, hints ...store.LayeredStoreHint) ([]*model.Reaction, *model.AppError) {
|
|
||||||
_va := make([]interface{}, len(hints))
|
|
||||||
for _i := range hints {
|
|
||||||
_va[_i] = hints[_i]
|
|
||||||
}
|
|
||||||
var _ca []interface{}
|
|
||||||
_ca = append(_ca, ctx, postId)
|
|
||||||
_ca = append(_ca, _va...)
|
|
||||||
ret := _m.Called(_ca...)
|
|
||||||
|
|
||||||
var r0 []*model.Reaction
|
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, string, ...store.LayeredStoreHint) []*model.Reaction); ok {
|
|
||||||
r0 = rf(ctx, postId, hints...)
|
|
||||||
} else {
|
|
||||||
if ret.Get(0) != nil {
|
|
||||||
r0 = ret.Get(0).([]*model.Reaction)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var r1 *model.AppError
|
|
||||||
if rf, ok := ret.Get(1).(func(context.Context, string, ...store.LayeredStoreHint) *model.AppError); ok {
|
|
||||||
r1 = rf(ctx, postId, hints...)
|
|
||||||
} else {
|
|
||||||
if ret.Get(1) != nil {
|
|
||||||
r1 = ret.Get(1).(*model.AppError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return r0, r1
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReactionPermanentDeleteBatch provides a mock function with given fields: ctx, endTime, limit, hints
|
|
||||||
func (_m *LayeredStoreSupplier) ReactionPermanentDeleteBatch(ctx context.Context, endTime int64, limit int64, hints ...store.LayeredStoreHint) (int64, *model.AppError) {
|
|
||||||
_va := make([]interface{}, len(hints))
|
|
||||||
for _i := range hints {
|
|
||||||
_va[_i] = hints[_i]
|
|
||||||
}
|
|
||||||
var _ca []interface{}
|
|
||||||
_ca = append(_ca, ctx, endTime, limit)
|
|
||||||
_ca = append(_ca, _va...)
|
|
||||||
ret := _m.Called(_ca...)
|
|
||||||
|
|
||||||
var r0 int64
|
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, int64, int64, ...store.LayeredStoreHint) int64); ok {
|
|
||||||
r0 = rf(ctx, endTime, limit, hints...)
|
|
||||||
} else {
|
|
||||||
r0 = ret.Get(0).(int64)
|
|
||||||
}
|
|
||||||
|
|
||||||
var r1 *model.AppError
|
|
||||||
if rf, ok := ret.Get(1).(func(context.Context, int64, int64, ...store.LayeredStoreHint) *model.AppError); ok {
|
|
||||||
r1 = rf(ctx, endTime, limit, hints...)
|
|
||||||
} else {
|
|
||||||
if ret.Get(1) != nil {
|
|
||||||
r1 = ret.Get(1).(*model.AppError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return r0, r1
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReactionSave provides a mock function with given fields: ctx, reaction, hints
|
|
||||||
func (_m *LayeredStoreSupplier) ReactionSave(ctx context.Context, reaction *model.Reaction, hints ...store.LayeredStoreHint) (*model.Reaction, *model.AppError) {
|
|
||||||
_va := make([]interface{}, len(hints))
|
|
||||||
for _i := range hints {
|
|
||||||
_va[_i] = hints[_i]
|
|
||||||
}
|
|
||||||
var _ca []interface{}
|
|
||||||
_ca = append(_ca, ctx, reaction)
|
|
||||||
_ca = append(_ca, _va...)
|
|
||||||
ret := _m.Called(_ca...)
|
|
||||||
|
|
||||||
var r0 *model.Reaction
|
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, *model.Reaction, ...store.LayeredStoreHint) *model.Reaction); ok {
|
|
||||||
r0 = rf(ctx, reaction, hints...)
|
|
||||||
} else {
|
|
||||||
if ret.Get(0) != nil {
|
|
||||||
r0 = ret.Get(0).(*model.Reaction)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var r1 *model.AppError
|
|
||||||
if rf, ok := ret.Get(1).(func(context.Context, *model.Reaction, ...store.LayeredStoreHint) *model.AppError); ok {
|
|
||||||
r1 = rf(ctx, reaction, hints...)
|
|
||||||
} else {
|
|
||||||
if ret.Get(1) != nil {
|
|
||||||
r1 = ret.Get(1).(*model.AppError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return r0, r1
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReactionsBulkGetForPosts provides a mock function with given fields: ctx, postIds, hints
|
|
||||||
func (_m *LayeredStoreSupplier) ReactionsBulkGetForPosts(ctx context.Context, postIds []string, hints ...store.LayeredStoreHint) ([]*model.Reaction, *model.AppError) {
|
|
||||||
_va := make([]interface{}, len(hints))
|
|
||||||
for _i := range hints {
|
|
||||||
_va[_i] = hints[_i]
|
|
||||||
}
|
|
||||||
var _ca []interface{}
|
|
||||||
_ca = append(_ca, ctx, postIds)
|
|
||||||
_ca = append(_ca, _va...)
|
|
||||||
ret := _m.Called(_ca...)
|
|
||||||
|
|
||||||
var r0 []*model.Reaction
|
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, []string, ...store.LayeredStoreHint) []*model.Reaction); ok {
|
|
||||||
r0 = rf(ctx, postIds, hints...)
|
|
||||||
} else {
|
|
||||||
if ret.Get(0) != nil {
|
|
||||||
r0 = ret.Get(0).([]*model.Reaction)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var r1 *model.AppError
|
|
||||||
if rf, ok := ret.Get(1).(func(context.Context, []string, ...store.LayeredStoreHint) *model.AppError); ok {
|
|
||||||
r1 = rf(ctx, postIds, hints...)
|
|
||||||
} else {
|
|
||||||
if ret.Get(1) != nil {
|
|
||||||
r1 = ret.Get(1).(*model.AppError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return r0, r1
|
|
||||||
}
|
|
||||||
|
|
||||||
// RoleDelete provides a mock function with given fields: ctx, roldId, hints
|
// RoleDelete provides a mock function with given fields: ctx, roldId, hints
|
||||||
func (_m *LayeredStoreSupplier) RoleDelete(ctx context.Context, roldId string, hints ...store.LayeredStoreHint) (*model.Role, *model.AppError) {
|
func (_m *LayeredStoreSupplier) RoleDelete(ctx context.Context, roldId string, hints ...store.LayeredStoreHint) (*model.Role, *model.AppError) {
|
||||||
_va := make([]interface{}, len(hints))
|
_va := make([]interface{}, len(hints))
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user