MM-10272: Add a count for pinned posts header icon (#11840)

This commit is contained in:
Woolim Cho
2019-09-04 20:41:29 +09:00
committed by Ben Schumacher
parent 5a477a617a
commit b9a3c2e90e
11 changed files with 231 additions and 4 deletions

View File

@@ -35,6 +35,9 @@ const (
CHANNEL_GUESTS_COUNTS_CACHE_SIZE = model.CHANNEL_CACHE_SIZE
CHANNEL_GUESTS_COUNTS_CACHE_SEC = 1800 // 30 mins
CHANNEL_PINNEDPOSTS_COUNTS_CACHE_SIZE = model.CHANNEL_CACHE_SIZE
CHANNEL_PINNEDPOSTS_COUNTS_CACHE_SEC = 1800 // 30 mins
CHANNEL_CACHE_SEC = 900 // 15 mins
)
@@ -281,6 +284,7 @@ type publicChannel struct {
}
var channelMemberCountsCache = utils.NewLru(CHANNEL_MEMBERS_COUNTS_CACHE_SIZE)
var channelPinnedPostCountsCache = utils.NewLru(CHANNEL_PINNEDPOSTS_COUNTS_CACHE_SIZE)
var channelGuestCountsCache = utils.NewLru(CHANNEL_GUESTS_COUNTS_CACHE_SIZE)
var allChannelMembersForUserCache = utils.NewLru(ALL_CHANNEL_MEMBERS_FOR_USER_CACHE_SIZE)
var allChannelMembersNotifyPropsForChannelCache = utils.NewLru(ALL_CHANNEL_MEMBERS_NOTIFY_PROPS_FOR_CHANNEL_CACHE_SIZE)
@@ -289,6 +293,7 @@ var channelByNameCache = utils.NewLru(model.CHANNEL_CACHE_SIZE)
func (s SqlChannelStore) ClearCaches() {
channelMemberCountsCache.Purge()
channelPinnedPostCountsCache.Purge()
channelGuestCountsCache.Purge()
allChannelMembersForUserCache.Purge()
allChannelMembersNotifyPropsForChannelCache.Purge()
@@ -297,6 +302,7 @@ func (s SqlChannelStore) ClearCaches() {
if s.metrics != nil {
s.metrics.IncrementMemCacheInvalidationCounter("Channel Member Counts - Purge")
s.metrics.IncrementMemCacheInvalidationCounter("Channel Pinned Post Counts - Purge")
s.metrics.IncrementMemCacheInvalidationCounter("All Channel Members for User - Purge")
s.metrics.IncrementMemCacheInvalidationCounter("All Channel Members Notify Props for Channel - Purge")
s.metrics.IncrementMemCacheInvalidationCounter("Channel - Purge")
@@ -1626,6 +1632,66 @@ func (s SqlChannelStore) GetMemberCount(channelId string, allowFromCache bool) (
return count, nil
}
func (s SqlChannelStore) InvalidatePinnedPostCount(channelId string) {
channelPinnedPostCountsCache.Remove(channelId)
if s.metrics != nil {
s.metrics.IncrementMemCacheInvalidationCounter("Channel Pinned Post Counts - Remove by ChannelId")
}
}
func (s SqlChannelStore) GetPinnedPostCountFromCache(channelId string) int64 {
if cacheItem, ok := channelPinnedPostCountsCache.Get(channelId); ok {
if s.metrics != nil {
s.metrics.IncrementMemCacheHitCounter("Channel Pinned Post Counts")
}
return cacheItem.(int64)
}
if s.metrics != nil {
s.metrics.IncrementMemCacheMissCounter("Channel Pinned Post Counts")
}
count, err := s.GetPinnedPostCount(channelId, true)
if err != nil {
return 0
}
return count
}
func (s SqlChannelStore) GetPinnedPostCount(channelId string, allowFromCache bool) (int64, *model.AppError) {
if allowFromCache {
if cacheItem, ok := channelPinnedPostCountsCache.Get(channelId); ok {
if s.metrics != nil {
s.metrics.IncrementMemCacheHitCounter("Channel Pinned Post Counts")
}
return cacheItem.(int64), nil
}
}
if s.metrics != nil {
s.metrics.IncrementMemCacheMissCounter("Channel Pinned Post Counts")
}
count, err := s.GetReplica().SelectInt(`
SELECT count(*)
FROM Posts
WHERE
IsPinned = true
AND ChannelId = :ChannelId
AND DeleteAt = 0`, map[string]interface{}{"ChannelId": channelId})
if err != nil {
return 0, model.NewAppError("SqlChannelStore.GetPinnedPostCount", "store.sql_channel.get_pinnedpost_count.app_error", nil, "channel_id="+channelId+", "+err.Error(), http.StatusInternalServerError)
}
if allowFromCache {
channelPinnedPostCountsCache.AddWithExpiresInSecs(channelId, count, CHANNEL_PINNEDPOSTS_COUNTS_CACHE_SEC)
}
return count, nil
}
func (s SqlChannelStore) InvalidateGuestCount(channelId string) {
channelGuestCountsCache.Remove(channelId)
if s.metrics != nil {

View File

@@ -148,6 +148,9 @@ type ChannelStore interface {
InvalidateMemberCount(channelId string)
GetMemberCountFromCache(channelId string) int64
GetMemberCount(channelId string, allowFromCache bool) (int64, *model.AppError)
InvalidatePinnedPostCount(channelId string)
GetPinnedPostCountFromCache(channelId string) int64
GetPinnedPostCount(channelId string, allowFromCache bool) (int64, *model.AppError)
InvalidateGuestCount(channelId string)
GetGuestCountFromCache(channelId string) int64
GetGuestCount(channelId string, allowFromCache bool) (int64, *model.AppError)

View File

@@ -75,6 +75,7 @@ func TestChannelStore(t *testing.T, ss store.Store, s SqlSupplier) {
t.Run("SearchGroupChannels", func(t *testing.T) { testChannelStoreSearchGroupChannels(t, ss) })
t.Run("AnalyticsDeletedTypeCount", func(t *testing.T) { testChannelStoreAnalyticsDeletedTypeCount(t, ss) })
t.Run("GetPinnedPosts", func(t *testing.T) { testChannelStoreGetPinnedPosts(t, ss) })
t.Run("GetPinnedPostCount", func(t *testing.T) { testChannelStoreGetPinnedPostCount(t, ss) })
t.Run("MaxChannelsPerTeam", func(t *testing.T) { testChannelStoreMaxChannelsPerTeam(t, ss) })
t.Run("GetChannelsByScheme", func(t *testing.T) { testChannelStoreGetChannelsByScheme(t, ss) })
t.Run("MigrateChannelMembers", func(t *testing.T) { testChannelStoreMigrateChannelMembers(t, ss) })
@@ -3379,6 +3380,78 @@ func testChannelStoreGetPinnedPosts(t *testing.T, ss store.Store) {
}
}
func testChannelStoreGetPinnedPostCount(t *testing.T, ss store.Store) {
ch1 := &model.Channel{
TeamId: model.NewId(),
DisplayName: "Name",
Name: "zz" + model.NewId() + "b",
Type: model.CHANNEL_OPEN,
}
o1, err := ss.Channel().Save(ch1, -1)
require.Nil(t, err)
_, err = ss.Post().Save(&model.Post{
UserId: model.NewId(),
ChannelId: o1.Id,
Message: "test",
IsPinned: true,
})
require.Nil(t, err)
_, err = ss.Post().Save(&model.Post{
UserId: model.NewId(),
ChannelId: o1.Id,
Message: "test",
IsPinned: true,
})
require.Nil(t, err)
if count, errGet := ss.Channel().GetPinnedPostCount(o1.Id, true); errGet != nil {
t.Fatal(errGet)
} else if count != 2 {
t.Fatal("didn't return right count")
}
if ss.Channel().GetPinnedPostCountFromCache(o1.Id) != 2 {
t.Fatal("should have saved 2 pinned post count ")
}
ch2 := &model.Channel{
TeamId: model.NewId(),
DisplayName: "Name",
Name: "zz" + model.NewId() + "b",
Type: model.CHANNEL_OPEN,
}
o2, err := ss.Channel().Save(ch2, -1)
require.Nil(t, err)
_, err = ss.Post().Save(&model.Post{
UserId: model.NewId(),
ChannelId: o2.Id,
Message: "test",
})
require.Nil(t, err)
_, err = ss.Post().Save(&model.Post{
UserId: model.NewId(),
ChannelId: o2.Id,
Message: "test",
})
require.Nil(t, err)
if count, errGet := ss.Channel().GetPinnedPostCount(o2.Id, true); errGet != nil {
t.Fatal(errGet)
} else if count != 0 {
t.Fatal("should return 0")
}
if ss.Channel().GetPinnedPostCountFromCache(o2.Id) != 0 {
t.Fatal("should have saved 0 pinned post count ")
}
}
func testChannelStoreMaxChannelsPerTeam(t *testing.T, ss store.Store) {
channel := &model.Channel{
TeamId: model.NewId(),

View File

@@ -993,6 +993,43 @@ func (_m *ChannelStore) GetMoreChannels(teamId string, userId string, offset int
return r0, r1
}
// GetPinnedPostCount provides a mock function with given fields: channelId, allowFromCache
func (_m *ChannelStore) GetPinnedPostCount(channelId string, allowFromCache bool) (int64, *model.AppError) {
ret := _m.Called(channelId, allowFromCache)
var r0 int64
if rf, ok := ret.Get(0).(func(string, bool) int64); ok {
r0 = rf(channelId, allowFromCache)
} else {
r0 = ret.Get(0).(int64)
}
var r1 *model.AppError
if rf, ok := ret.Get(1).(func(string, bool) *model.AppError); ok {
r1 = rf(channelId, allowFromCache)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*model.AppError)
}
}
return r0, r1
}
// GetPinnedPostCountFromCache provides a mock function with given fields: channelId
func (_m *ChannelStore) GetPinnedPostCountFromCache(channelId string) int64 {
ret := _m.Called(channelId)
var r0 int64
if rf, ok := ret.Get(0).(func(string) int64); ok {
r0 = rf(channelId)
} else {
r0 = ret.Get(0).(int64)
}
return r0
}
// GetPinnedPosts provides a mock function with given fields: channelId
func (_m *ChannelStore) GetPinnedPosts(channelId string) (*model.PostList, *model.AppError) {
ret := _m.Called(channelId)
@@ -1139,6 +1176,11 @@ func (_m *ChannelStore) InvalidateMemberCount(channelId string) {
_m.Called(channelId)
}
// InvalidatePinnedPostCount provides a mock function with given fields: channelId
func (_m *ChannelStore) InvalidatePinnedPostCount(channelId string) {
_m.Called(channelId)
}
// IsUserInChannelUseCache provides a mock function with given fields: userId, channelId
func (_m *ChannelStore) IsUserInChannelUseCache(userId string, channelId string) bool {
ret := _m.Called(userId, channelId)

View File

@@ -1382,6 +1382,23 @@ func (s *TimerLayerChannelStore) InvalidateMemberCount(channelId string) {
return
}
func (s *TimerLayerChannelStore) InvalidatePinnedPostCount(channelId string) {
start := timemodule.Now()
s.ChannelStore.InvalidatePinnedPostCount(channelId)
t := timemodule.Now()
elapsed := t.Sub(start)
if s.Root.Metrics != nil {
success := "false"
if true {
success = "true"
}
s.Root.Metrics.ObserveStoreMethodDuration("ChannelStore.InvalidatePinnedPostCount", success, float64(elapsed))
}
return
}
func (s *TimerLayerChannelStore) IsUserInChannelUseCache(userId string, channelId string) bool {
start := timemodule.Now()