[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>
Этот коммит содержится в:
@@ -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
Обычный файл
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
Обычный файл
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)
|
||||
})
|
||||
}
|
||||
Ссылка в новой задаче
Block a user