From 0f5d160131afce750c5f0ec10027463d2282fd2d Mon Sep 17 00:00:00 2001 From: Agniva De Sarker Date: Tue, 10 Dec 2024 11:08:17 +0530 Subject: [PATCH] MM-62077: Fix cluster broadcast for LRU caches (#29488) We were incorrectly not broadcasting status cache updates inspite of that being an LRU cache. We were also not doing it for profilesInChannel cache. Now we fix it by properly checking the invalidationEvent which is something local to the cache itself rather than the cache provider. https://mattermost.atlassian.net/browse/MM-62077 ```release-note NONE ``` --- .../channels/app/platform/cluster_handlers.go | 2 +- server/channels/app/platform/status.go | 2 +- .../channels/store/localcachelayer/layer.go | 6 ++-- .../store/localcachelayer/layer_test.go | 34 +++++++++++++++++++ 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/server/channels/app/platform/cluster_handlers.go b/server/channels/app/platform/cluster_handlers.go index ae36e288893..b6b56da1246 100644 --- a/server/channels/app/platform/cluster_handlers.go +++ b/server/channels/app/platform/cluster_handlers.go @@ -134,7 +134,7 @@ func (ps *PlatformService) InvalidateAllCachesSkipSend() { func (ps *PlatformService) InvalidateAllCaches() *model.AppError { ps.InvalidateAllCachesSkipSend() - if ps.clusterIFace != nil && *ps.Config().CacheSettings.CacheType == model.CacheTypeLRU { + if ps.clusterIFace != nil { msg := &model.ClusterMessage{ Event: model.ClusterEventInvalidateAllCaches, SendType: model.ClusterSendReliable, diff --git a/server/channels/app/platform/status.go b/server/channels/app/platform/status.go index b15e3ace8a3..5aee2f3abba 100644 --- a/server/channels/app/platform/status.go +++ b/server/channels/app/platform/status.go @@ -21,7 +21,7 @@ func (ps *PlatformService) AddStatusCacheSkipClusterSend(status *model.Status) { func (ps *PlatformService) AddStatusCache(status *model.Status) { ps.AddStatusCacheSkipClusterSend(status) - if ps.Cluster() != nil && *ps.Config().CacheSettings.CacheType == model.CacheTypeLRU { + if ps.Cluster() != nil { statusJSON, err := json.Marshal(status) if err != nil { ps.logger.Warn("Failed to encode status to JSON", mlog.Err(err)) diff --git a/server/channels/store/localcachelayer/layer.go b/server/channels/store/localcachelayer/layer.go index 1003a01d610..a489ab82261 100644 --- a/server/channels/store/localcachelayer/layer.go +++ b/server/channels/store/localcachelayer/layer.go @@ -448,7 +448,7 @@ func (s *LocalCacheStore) doInvalidateCacheCluster(cache cache.Cache, key string if err != nil { s.logger.Warn("Error while removing cache entry", mlog.Err(err), mlog.String("cache_name", cache.Name())) } - if s.cluster != nil && s.cacheType == model.CacheTypeLRU { + if s.cluster != nil && cache.GetInvalidateClusterEvent() != model.ClusterEventNone { msg := &model.ClusterMessage{ Event: cache.GetInvalidateClusterEvent(), SendType: model.ClusterSendBestEffort, @@ -466,7 +466,7 @@ func (s *LocalCacheStore) doMultiInvalidateCacheCluster(cache cache.Cache, keys if err != nil { s.logger.Warn("Error while removing cache entry", mlog.Err(err), mlog.String("cache_name", cache.Name())) } - if s.cluster != nil && s.cacheType == model.CacheTypeLRU { + if s.cluster != nil && cache.GetInvalidateClusterEvent() != model.ClusterEventNone { for _, key := range keys { msg := &model.ClusterMessage{ Event: cache.GetInvalidateClusterEvent(), @@ -538,7 +538,7 @@ func (s *LocalCacheStore) doClearCacheCluster(cache cache.Cache) { if err != nil { s.logger.Warn("Error while purging cache", mlog.Err(err), mlog.String("cache_name", cache.Name())) } - if s.cluster != nil && s.cacheType == model.CacheTypeLRU { + if s.cluster != nil && cache.GetInvalidateClusterEvent() != model.ClusterEventNone { msg := &model.ClusterMessage{ Event: cache.GetInvalidateClusterEvent(), SendType: model.ClusterSendBestEffort, diff --git a/server/channels/store/localcachelayer/layer_test.go b/server/channels/store/localcachelayer/layer_test.go index 453337b5d66..b02c2f56596 100644 --- a/server/channels/store/localcachelayer/layer_test.go +++ b/server/channels/store/localcachelayer/layer_test.go @@ -14,7 +14,10 @@ import ( "github.com/mattermost/mattermost/server/v8/channels/store" "github.com/mattermost/mattermost/server/v8/channels/store/sqlstore" "github.com/mattermost/mattermost/server/v8/channels/store/storetest" + "github.com/mattermost/mattermost/server/v8/channels/testlib" "github.com/mattermost/mattermost/server/v8/platform/services/cache" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" ) @@ -148,3 +151,34 @@ func tearDownStores() { wg.Wait() }) } + +func TestClearCacheCluster(t *testing.T) { + cluster := &testlib.FakeClusterInterface{} + lc := &LocalCacheStore{ + cluster: cluster, + } + + c := cache.NewLRU(&cache.CacheOptions{ + Size: 10, + Name: "test", + InvalidateClusterEvent: model.ClusterEventInvalidateCacheForRoles, + }) + + lc.doClearCacheCluster(c) + assert.Len(t, cluster.GetMessages(), 1) + expectedMsg := &model.ClusterMessage{ + Event: model.ClusterEventInvalidateCacheForRoles, + SendType: model.ClusterSendBestEffort, + Data: clearCacheMessageData, + } + require.Equal(t, expectedMsg, cluster.GetMessages()[0]) + + c = cache.NewLRU(&cache.CacheOptions{ + Size: 10, + Name: "test", + InvalidateClusterEvent: model.ClusterEventNone, + }) + + lc.doClearCacheCluster(c) + assert.Len(t, cluster.GetMessages(), 1) +}