MM-59933: Increment/Decrement the member count directly (#28196)

While using Redis, there is no need to invalidate
and then update the new count from the DB when
we know the exact number it is going to be incremented
or decremented by.

In that case, we can directly use Redis primitives
to update the cache and prevent yet another DB query.

To achieve this, we modify the LRU cache get/set
paths slightly to not marshal into byte slices
for *int64 values. This is needed for Redis to operate
the INCR/DECR commands.

https://mattermost.atlassian.net/browse/MM-59933

```release-note
NONE
```

Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
Agniva De Sarker
2024-09-19 09:38:38 +05:30
коммит произвёл GitHub
родитель da24e0c4da
Коммит 7be7a47fd3
5 изменённых файлов: 402 добавлений и 28 удалений

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

@@ -441,8 +441,13 @@ func (s LocalCacheChannelStore) SaveMember(rctx request.CTX, member *model.Chann
if err != nil {
return nil, err
}
// For redis, directly increment member count.
s.InvalidateMemberCount(member.ChannelId)
if externalCache, ok := s.rootStore.channelMemberCountsCache.(cache.ExternalCache); ok {
s.rootStore.doIncrementCache(externalCache, member.ChannelId, 1)
} else {
s.InvalidateMemberCount(member.ChannelId)
}
return member, nil
}
@@ -452,7 +457,15 @@ func (s LocalCacheChannelStore) SaveMultipleMembers(members []*model.ChannelMemb
return nil, err
}
for _, member := range members {
s.InvalidateMemberCount(member.ChannelId)
// For redis, directly increment member count.
// It should be possible to group the members from the slice
// by channelID and increment it once per channel. But it depends
// on whether all members are part of the same channel or not.
if externalCache, ok := s.rootStore.channelMemberCountsCache.(cache.ExternalCache); ok {
s.rootStore.doIncrementCache(externalCache, member.ChannelId, 1)
} else {
s.InvalidateMemberCount(member.ChannelId)
}
}
return members, nil
}
@@ -522,8 +535,13 @@ func (s LocalCacheChannelStore) RemoveMember(rctx request.CTX, channelId, userId
if err != nil {
return err
}
// For redis, directly decrement member count
s.InvalidateMemberCount(channelId)
// For redis, directly decrement member count.
if externalCache, ok := s.rootStore.channelMemberCountsCache.(cache.ExternalCache); ok {
s.rootStore.doDecrementCache(externalCache, channelId, 1)
} else {
s.InvalidateMemberCount(channelId)
}
return nil
}
@@ -532,7 +550,11 @@ func (s LocalCacheChannelStore) RemoveMembers(rctx request.CTX, channelId string
if err != nil {
return err
}
// For redis, directly decrement member count
s.InvalidateMemberCount(channelId)
// For redis, directly decrement member count.
if externalCache, ok := s.rootStore.channelMemberCountsCache.(cache.ExternalCache); ok {
s.rootStore.doDecrementCache(externalCache, channelId, len(userIds))
} else {
s.InvalidateMemberCount(channelId)
}
return nil
}

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

@@ -526,6 +526,20 @@ func (s *LocalCacheStore) doMultiReadCache(cache cache.Cache, keys []string, val
return errs
}
func (s *LocalCacheStore) doIncrementCache(cache cache.ExternalCache, key string, val int) {
err := cache.Increment(key, val)
if err != nil {
s.logger.Warn("Error while incrementing cache entry", mlog.Err(err), mlog.String("cache_name", cache.Name()))
}
}
func (s *LocalCacheStore) doDecrementCache(cache cache.ExternalCache, key string, val int) {
err := cache.Decrement(key, val)
if err != nil {
s.logger.Warn("Error while decrementing cache entry", mlog.Err(err), mlog.String("cache_name", cache.Name()))
}
}
func (s *LocalCacheStore) doClearCacheCluster(cache cache.Cache) {
err := cache.Purge()
if err != nil {