[MM-43917] Cloud Freemium limits API: messages/posts (#20152)

* WIP - Add api and app funcs

* Add test cases

* Add utils testcases

* Exclude deleted posts

* Add doc for func

* Move api from cloud to usage

* Allow api access to authenticated users

* Change int to int64

* Fix lint issue

* Simplify err check

Co-authored-by: Ashish Bhate <ashish.bhate@mattermost.com>

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Co-authored-by: Ashish Bhate <ashish.bhate@mattermost.com>
Этот коммит содержится в:
Vishal
2022-05-17 17:00:40 +05:30
коммит произвёл GitHub
родитель 9c851e996c
Коммит fd703a365b
29 изменённых файлов: 341 добавлений и 43 удалений

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

@@ -87,7 +87,7 @@ func (a *App) GetAnalytics(name string, teamID string) (model.AnalyticsRows, *mo
if !skipIntensiveQueries {
g.Go(func() error {
var err error
if postsCount, err = a.Srv().Store.Post().AnalyticsPostCount(teamID, false, false); err != nil {
if postsCount, err = a.Srv().Store.Post().AnalyticsPostCount(&model.PostCountOptions{TeamId: teamID}); err != nil {
return model.NewAppError("GetAnalytics", "app.post.analytics_posts_count.app_error", nil, err.Error(), http.StatusInternalServerError)
}
return nil
@@ -269,7 +269,7 @@ func (a *App) GetAnalytics(name string, teamID string) (model.AnalyticsRows, *mo
if !skipIntensiveQueries {
g2.Go(func() error {
var err error
if filesCount, err = a.Srv().Store.Post().AnalyticsPostCount(teamID, true, false); err != nil {
if filesCount, err = a.Srv().Store.Post().AnalyticsPostCount(&model.PostCountOptions{TeamId: teamID, MustHaveFile: true}); err != nil {
return model.NewAppError("GetAnalytics", "app.post.analytics_posts_count.app_error", nil, err.Error(), http.StatusInternalServerError)
}
return nil
@@ -277,7 +277,7 @@ func (a *App) GetAnalytics(name string, teamID string) (model.AnalyticsRows, *mo
g2.Go(func() error {
var err error
if hashtagsCount, err = a.Srv().Store.Post().AnalyticsPostCount(teamID, false, true); err != nil {
if hashtagsCount, err = a.Srv().Store.Post().AnalyticsPostCount(&model.PostCountOptions{TeamId: teamID, MustHaveHashtag: true}); err != nil {
return model.NewAppError("GetAnalytics", "app.post.analytics_posts_count.app_error", nil, err.Error(), http.StatusInternalServerError)
}
return nil

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

@@ -187,6 +187,8 @@ type AppIface interface {
// To get the plugins environment when the plugins are disabled, manually acquire the plugins
// lock instead.
GetPluginsEnvironment() *plugin.Environment
// GetPostsUsage returns "rounded off" total posts count like returns 900 instead of 987
GetPostsUsage() (int64, *model.AppError)
// GetProductNotices is called from the frontend to fetch the product notices that are relevant to the caller
GetProductNotices(c *request.Context, userID, teamID string, client model.NoticeClientType, clientVersion string, locale string) (model.NoticeMessages, *model.AppError)
// GetPublicKey will return the actual public key saved in the `name` file.

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

@@ -1964,7 +1964,7 @@ func TestImportimportMultiplePostLines(t *testing.T) {
require.Nil(t, err, "Failed to get user from database.")
// Count the number of posts in the testing team.
initialPostCount, nErr := th.App.Srv().Store.Post().AnalyticsPostCount(team.Id, false, false)
initialPostCount, nErr := th.App.Srv().Store.Post().AnalyticsPostCount(&model.PostCountOptions{TeamId: team.Id})
require.NoError(t, nErr)
// Try adding an invalid post in dry run mode.
@@ -2470,7 +2470,7 @@ func TestImportimportMultiplePostLines(t *testing.T) {
require.Nil(t, err, "Failed to get channel from database.")
// Count the number of posts in the team2.
initialPostCountForTeam2, nErr := th.App.Srv().Store.Post().AnalyticsPostCount(team2.Id, false, false)
initialPostCountForTeam2, nErr := th.App.Srv().Store.Post().AnalyticsPostCount(&model.PostCountOptions{TeamId: team2.Id})
require.NoError(t, nErr)
// Try adding two valid posts in apply mode.
@@ -2576,7 +2576,7 @@ func TestImportImportPost(t *testing.T) {
require.Nil(t, appErr, "Failed to get user from database.")
// Count the number of posts in the testing team.
initialPostCount, nErr := th.App.Srv().Store.Post().AnalyticsPostCount(team.Id, false, false)
initialPostCount, nErr := th.App.Srv().Store.Post().AnalyticsPostCount(&model.PostCountOptions{TeamId: team.Id})
require.NoError(t, nErr)
time := model.GetMillis()
@@ -3283,7 +3283,7 @@ func TestImportImportDirectPost(t *testing.T) {
directChannel = channel
// Get the number of posts in the system.
result, err := th.App.Srv().Store.Post().AnalyticsPostCount("", false, false)
result, err := th.App.Srv().Store.Post().AnalyticsPostCount(&model.PostCountOptions{})
require.NoError(t, err)
initialPostCount := result
initialDate := model.GetMillis()
@@ -3644,7 +3644,7 @@ func TestImportImportDirectPost(t *testing.T) {
groupChannel = channel
// Get the number of posts in the system.
result, nErr := th.App.Srv().Store.Post().AnalyticsPostCount("", false, false)
result, nErr := th.App.Srv().Store.Post().AnalyticsPostCount(&model.PostCountOptions{})
require.NoError(t, nErr)
initialPostCount = result

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

@@ -68,7 +68,7 @@ func checkNoError(t *testing.T, err *model.AppError) {
}
func AssertAllPostsCount(t *testing.T, a *App, initialCount int64, change int64, teamName string) {
result, err := a.Srv().Store.Post().AnalyticsPostCount(teamName, false, false)
result, err := a.Srv().Store.Post().AnalyticsPostCount(&model.PostCountOptions{TeamId: teamName})
require.NoError(t, err)
require.Equal(t, initialCount+change, result, "Did not find the expected number of posts.")
}

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

@@ -464,7 +464,7 @@ func (s *Server) doFirstAdminSetupCompleteMigration() {
}
// if there are teams, then if this isn't a new installation, there should be posts
postCount, err := s.Store.Post().AnalyticsPostCount("", false, false)
postCount, err := s.Store.Post().AnalyticsPostCount(&model.PostCountOptions{})
if err != nil || postCount < existingInstallationPostsThreshold {
return
}

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

@@ -7832,6 +7832,28 @@ func (a *OpenTracingAppLayer) GetPostsSince(options model.GetPostsSinceOptions)
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) GetPostsUsage() (int64, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetPostsUsage")
a.ctx = newCtx
a.app.Srv().Store.SetContext(newCtx)
defer func() {
a.app.Srv().Store.SetContext(origCtx)
a.ctx = origCtx
}()
defer span.Finish()
resultVar0, resultVar1 := a.app.GetPostsUsage()
if resultVar1 != nil {
span.LogFields(spanlog.Error(resultVar1))
ext.Error.Set(span, true)
}
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) GetPreferenceByCategoryAndNameForUser(userID string, category string, preferenceName string) (*model.Preference, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetPreferenceByCategoryAndNameForUser")

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

@@ -343,7 +343,7 @@ func (a *App) UpdateProductNotices() *model.AppError {
skip := *a.Config().AnnouncementSettings.NoticesSkipCache
mlog.Debug("Will fetch notices from", mlog.String("url", url), mlog.Bool("skip_cache", skip))
var err error
a.ch.cachedPostCount, err = a.Srv().Store.Post().AnalyticsPostCount("", false, false)
a.ch.cachedPostCount, err = a.Srv().Store.Post().AnalyticsPostCount(&model.PostCountOptions{})
if err != nil {
mlog.Warn("Failed to fetch post count", mlog.String("error", err.Error()))
}

21
app/usage.go Обычный файл
Просмотреть файл

@@ -0,0 +1,21 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package app
import (
"net/http"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/utils"
)
// GetPostsUsage returns "rounded off" total posts count like returns 900 instead of 987
func (a *App) GetPostsUsage() (int64, *model.AppError) {
count, err := a.Srv().Store.Post().AnalyticsPostCount(&model.PostCountOptions{ExcludeDeleted: true})
if err != nil {
return 0, model.NewAppError("GetPostsUsage", "app.post.analytics_posts_count.app_error", nil, err.Error(), http.StatusInternalServerError)
}
return utils.RoundOffToZeroes(float64(count)), nil
}

49
app/usage_test.go Обычный файл
Просмотреть файл

@@ -0,0 +1,49 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package app
import (
"errors"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/mattermost/mattermost-server/v6/store/storetest/mocks"
)
func TestGetPostsUsage(t *testing.T) {
t.Run("returns error when AnalyticsPostCount fails", func(t *testing.T) {
th := SetupWithStoreMock(t)
defer th.TearDown()
errMsg := "Test posts count error"
mockStore := th.App.Srv().Store.(*mocks.Store)
mockPostStore := mocks.PostStore{}
mockPostStore.On("AnalyticsPostCount", mock.Anything).Return(int64(0), errors.New(errMsg))
mockStore.On("Post").Return(&mockPostStore)
usage, appErr := th.App.GetPostsUsage()
assert.Zero(t, usage)
assert.ErrorContains(t, appErr, errMsg)
})
t.Run("returns rounded off count when AnalyticsPostCount returns valid count", func(t *testing.T) {
th := SetupWithStoreMock(t)
defer th.TearDown()
var mockCount int64 = 4321
var expected int64 = 4000
mockStore := th.App.Srv().Store.(*mocks.Store)
mockPostStore := mocks.PostStore{}
mockPostStore.On("AnalyticsPostCount", mock.Anything).Return(mockCount, nil)
mockStore.On("Post").Return(&mockPostStore)
count, appErr := th.App.GetPostsUsage()
assert.Nil(t, appErr)
assert.Equal(t, expected, count)
})
}