From 22cdf289bae8d8211eafe9e12b1ffccc622eff50 Mon Sep 17 00:00:00 2001 From: Harshil Sharma Date: Mon, 28 Oct 2024 15:40:47 +0530 Subject: [PATCH 01/15] Added create scheduled posts --- go.work | 6 ++ loadtest/control/actions.go | 9 +++ .../control/simulcontroller/controller.go | 6 ++ .../simulcontroller/scheduled_posts.go | 68 +++++++++++++++++++ loadtest/store/memstore/store.go | 17 +++++ loadtest/store/store.go | 3 + loadtest/user/user.go | 3 + loadtest/user/userentity/scheduled_posts.go | 31 +++++++++ loadtest/utils.go | 18 +++++ 9 files changed, 161 insertions(+) create mode 100644 go.work create mode 100644 loadtest/control/simulcontroller/scheduled_posts.go create mode 100644 loadtest/user/userentity/scheduled_posts.go diff --git a/go.work b/go.work new file mode 100644 index 000000000..1d9a0b608 --- /dev/null +++ b/go.work @@ -0,0 +1,6 @@ +go 1.22.6 + +use ( + . + ../../go/src/github.com/mattermost/mattermost/server/public +) diff --git a/loadtest/control/actions.go b/loadtest/control/actions.go index f7526dcea..fdbe052f1 100644 --- a/loadtest/control/actions.go +++ b/loadtest/control/actions.go @@ -1032,6 +1032,15 @@ func DraftsEnabled(u user.User) (bool, UserActionResponse) { return allow, UserActionResponse{} } +func ScheduledPostsEnabled(u user.User) (bool, UserActionResponse) { + allow, err := strconv.ParseBool(u.Store().ClientConfig()["ScheduledPosts"]) + if err != nil { + return false, UserActionResponse{Err: NewUserError(err)} + } + + return allow, UserActionResponse{} +} + // MessageExport simulates the given user performing // a compliance message export func MessageExport(u user.User) UserActionResponse { diff --git a/loadtest/control/simulcontroller/controller.go b/loadtest/control/simulcontroller/controller.go index 666b05dc1..e722fe928 100644 --- a/loadtest/control/simulcontroller/controller.go +++ b/loadtest/control/simulcontroller/controller.go @@ -264,6 +264,12 @@ func getActionList(c *SimulController) []userAction { frequency: 1.41, minServerVersion: control.MinSupportedVersion, // 7.7.0 }, + { + name: "CreateScheduledPost", + run: c.createScheduledPost, + frequency: 0.05, + minServerVersion: control.UnreleasedVersion, + }, // All actions are required to contain a valid minServerVersion: // - If the action is present in server versions equal or older than // control.MinSupportedVersion, use control.MinSupportedVersion. diff --git a/loadtest/control/simulcontroller/scheduled_posts.go b/loadtest/control/simulcontroller/scheduled_posts.go new file mode 100644 index 000000000..20e5e179c --- /dev/null +++ b/loadtest/control/simulcontroller/scheduled_posts.go @@ -0,0 +1,68 @@ +package simulcontroller + +import ( + "fmt" + "github.com/mattermost/mattermost-load-test-ng/loadtest" + "github.com/mattermost/mattermost-load-test-ng/loadtest/control" + "github.com/mattermost/mattermost-load-test-ng/loadtest/user" + "github.com/mattermost/mattermost/server/public/model" + "math/rand" +) + +func (c *SimulController) createScheduledPost(u user.User) control.UserActionResponse { + if ok, resp := control.ScheduledPostsEnabled(u); resp.Err != nil { + return resp + } else if !ok { + return control.UserActionResponse{Info: "scheduled posts not enabled"} + } + + channel, err := u.Store().CurrentChannel() + if err != nil { + return control.UserActionResponse{Err: control.NewUserError(err)} + } + + var rootId = "" + // Assuming 25% of the scheduled posts are in a thread + if rand.Float64() < 0.25 { + post, err := u.Store().RandomPostForChannel(channel.Id) + if err == nil { + if post.RootId != "" { + rootId = post.RootId + } else { + rootId = post.Id + } + } + } + + if err := sendTypingEventIfEnabled(u, channel.Id); err != nil { + return control.UserActionResponse{Err: control.NewUserError(err)} + } + + message, err := createMessage(u, channel, false) + if err != nil { + return control.UserActionResponse{Err: control.NewUserError(err)} + } + + scheduledPost := &model.ScheduledPost{ + Draft: model.Draft{ + Message: message, + ChannelId: channel.Id, + RootId: rootId, + CreateAt: model.GetMillis(), + }, + ScheduledAt: loadtest.RandomFutureTime(17_28_00_000, 10), + } + + // 2% of the times post will have files attached. + if rand.Float64() < 0.02 { + if err := control.AttachFilesToDraft(u, &scheduledPost.Draft); err != nil { + return control.UserActionResponse{Err: control.NewUserError(err)} + } + } + + if err := u.CreateScheduledPost(channel.TeamId, scheduledPost); err != nil { + return control.UserActionResponse{Err: control.NewUserError(err)} + } + + return control.UserActionResponse{Info: fmt.Sprintf("scheudled post created in channel id %v", channel.Id)} +} diff --git a/loadtest/store/memstore/store.go b/loadtest/store/memstore/store.go index f114f7e28..52e9673b8 100644 --- a/loadtest/store/memstore/store.go +++ b/loadtest/store/memstore/store.go @@ -50,6 +50,7 @@ type MemStore struct { sidebarCategories map[string]map[string]*model.SidebarCategoryWithChannels drafts map[string]map[string]*model.Draft featureFlags map[string]bool + scheduledPosts map[string]map[string]*model.ScheduledPost } // New returns a new instance of MemStore with the given config. @@ -1221,3 +1222,19 @@ func (s *MemStore) SetDrafts(teamId string, drafts []*model.Draft) error { return nil } + +func (s *MemStore) SetScheduledPost(teamId, id string, scheduledPost *model.ScheduledPost) error { + s.lock.Lock() + defer s.lock.Unlock() + + if scheduledPost == nil { + return errors.New("memstore: scheduled post should not be nil") + } + + if s.scheduledPosts[teamId] == nil { + s.scheduledPosts[teamId] = map[string]*model.ScheduledPost{} + } + + s.scheduledPosts[teamId][id] = scheduledPost + return nil +} diff --git a/loadtest/store/store.go b/loadtest/store/store.go index 3f2a1b45a..b5b108ad3 100644 --- a/loadtest/store/store.go +++ b/loadtest/store/store.go @@ -181,6 +181,9 @@ type MutableUserStore interface { // SetDrafts stores the given drafts. SetDrafts(teamId string, drafts []*model.Draft) error + // scheduled posts + SetScheduledPost(teamId, id string, scheduledPost *model.ScheduledPost) error + // posts // SetPost stores the given post. SetPost(post *model.Post) error diff --git a/loadtest/user/user.go b/loadtest/user/user.go index 157a3cf30..6894a253f 100644 --- a/loadtest/user/user.go +++ b/loadtest/user/user.go @@ -325,4 +325,7 @@ type User interface { // GraphQL GetInitialDataGQL() error GetChannelsAndChannelMembersGQL(teamID string, includeDeleted bool, channelsCursor, channelMembersCursor string) (string, string, error) + + // Scheduled Posts + CreateScheduledPost(teamId string, scheduledPost *model.ScheduledPost) error } diff --git a/loadtest/user/userentity/scheduled_posts.go b/loadtest/user/userentity/scheduled_posts.go new file mode 100644 index 000000000..a650f166b --- /dev/null +++ b/loadtest/user/userentity/scheduled_posts.go @@ -0,0 +1,31 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +package userentity + +import ( + "context" + "github.com/mattermost/mattermost/server/public/model" +) + +func (ue *UserEntity) CreateScheduledPost(teamId string, scheduledPost *model.ScheduledPost) error { + user, err := ue.getUserFromStore() + if err != nil { + return err + } + + scheduledPost.UserId = user.Id + createdScheduledPost, _, err := ue.client.CreateScheduledPost(context.Background(), scheduledPost) + if err != nil { + return err + } + + id := scheduledPost.ChannelId + + if createdScheduledPost.RootId != "" { + id = scheduledPost.RootId + } + + return ue.store.SetScheduledPost(teamId, id, createdScheduledPost) + +} diff --git a/loadtest/utils.go b/loadtest/utils.go index b1b56b982..deaa1c48a 100644 --- a/loadtest/utils.go +++ b/loadtest/utils.go @@ -6,6 +6,8 @@ package loadtest import ( "errors" "fmt" + "math/rand" + "time" "github.com/mattermost/mattermost-load-test-ng/loadtest/control" "github.com/mattermost/mattermost-load-test-ng/loadtest/user/userentity" @@ -87,3 +89,19 @@ func nextPowerOf2(val int) int { val++ return val } + +// RandomFutureTime generates a random time between (now + xMilliseconds) to (now + xDays) in Unix milliseconds. +func RandomFutureTime(millisecondsFromNow int64, uptoDaysFromNow int) int64 { + now := time.Now() + minOffset := millisecondsFromNow // Minimum offset in milliseconds + maxOffset := millisecondsFromNow + int64(uptoDaysFromNow)*86400000 // Max offset in milliseconds (1 day = 86400000 ms) + + // Generate a random offset between minOffset and maxOffset + randomOffset := minOffset + rand.Int63n(maxOffset-minOffset) + + // Add the random offset to the current time + randomFutureTime := now.Add(time.Duration(randomOffset) * time.Millisecond) + + // Return the Unix timestamp in milliseconds + return randomFutureTime.UnixMilli() +} From 4341570520260881b76d65028da5460a071e8512 Mon Sep 17 00:00:00 2001 From: Harshil Sharma Date: Mon, 28 Oct 2024 16:06:29 +0530 Subject: [PATCH 02/15] Addded UpdateScheduledPost --- .../control/simulcontroller/controller.go | 6 +++ .../simulcontroller/scheduled_posts.go | 26 +++++++++++ loadtest/store/memstore/store.go | 45 +++++++++++++++++++ loadtest/store/store.go | 1 + loadtest/user/user.go | 2 + loadtest/user/userentity/scheduled_posts.go | 26 +++++++++++ 6 files changed, 106 insertions(+) diff --git a/loadtest/control/simulcontroller/controller.go b/loadtest/control/simulcontroller/controller.go index e722fe928..a6a29c754 100644 --- a/loadtest/control/simulcontroller/controller.go +++ b/loadtest/control/simulcontroller/controller.go @@ -270,6 +270,12 @@ func getActionList(c *SimulController) []userAction { frequency: 0.05, minServerVersion: control.UnreleasedVersion, }, + { + name: "UpdateScheduledPost", + run: c.updateScheduledPost, + frequency: 0.006, + minServerVersion: control.UnreleasedVersion, + }, // All actions are required to contain a valid minServerVersion: // - If the action is present in server versions equal or older than // control.MinSupportedVersion, use control.MinSupportedVersion. diff --git a/loadtest/control/simulcontroller/scheduled_posts.go b/loadtest/control/simulcontroller/scheduled_posts.go index 20e5e179c..88c56cc1d 100644 --- a/loadtest/control/simulcontroller/scheduled_posts.go +++ b/loadtest/control/simulcontroller/scheduled_posts.go @@ -66,3 +66,29 @@ func (c *SimulController) createScheduledPost(u user.User) control.UserActionRes return control.UserActionResponse{Info: fmt.Sprintf("scheudled post created in channel id %v", channel.Id)} } + +func (c *SimulController) updateScheduledPost(u user.User) control.UserActionResponse { + scheduledPost := u.GetRandomScheduledPost() + if scheduledPost == nil { + return control.UserActionResponse{Info: "no scheduled posts found"} + } + + channel, err := u.Store().CurrentChannel() + if err != nil { + return control.UserActionResponse{Err: control.NewUserError(err)} + } + + message, err := createMessage(u, channel, false) + if err != nil { + return control.UserActionResponse{Err: control.NewUserError(err)} + } + + scheduledPost.Message = message + scheduledPost.ScheduledAt = loadtest.RandomFutureTime(17_28_00_000, 10) + + if err := u.UpdateScheduledPost(channel.TeamId, scheduledPost); err != nil { + return control.UserActionResponse{Err: control.NewUserError(err)} + } + + return control.UserActionResponse{Info: fmt.Sprintf("scheudled post updated in channel id %v", channel.Id)} +} diff --git a/loadtest/store/memstore/store.go b/loadtest/store/memstore/store.go index 52e9673b8..051200584 100644 --- a/loadtest/store/memstore/store.go +++ b/loadtest/store/memstore/store.go @@ -6,6 +6,7 @@ package memstore import ( "errors" "fmt" + "math/rand" "sort" "strconv" "strings" @@ -1238,3 +1239,47 @@ func (s *MemStore) SetScheduledPost(teamId, id string, scheduledPost *model.Sche s.scheduledPosts[teamId][id] = scheduledPost return nil } + +func (s *MemStore) GetRandomScheduledPost() (*model.ScheduledPost, error) { + s.lock.RLock() + defer s.lock.RUnlock() + + // Seed the random generator + rand.Seed(time.Now().UnixNano()) + + // Check if scheduledPosts is empty + if len(s.scheduledPosts) == 0 { + return nil, errors.New("no scheduled posts available") + } + + // Pick a random index for the outer map + randomOuterIndex := rand.Intn(len(s.scheduledPosts)) + var selectedInnerMap map[string]*model.ScheduledPost + outerIndex := 0 + for _, innerMap := range s.scheduledPosts { + if outerIndex == randomOuterIndex { + selectedInnerMap = innerMap + break + } + outerIndex++ + } + + // Check if the selected inner map is empty + if len(selectedInnerMap) == 0 { + return nil, errors.New("no posts available in selected category") + } + + // Pick a random index for the inner map + randomInnerIndex := rand.Intn(len(selectedInnerMap)) + var selectedPost *model.ScheduledPost + innerIndex := 0 + for _, post := range selectedInnerMap { + if innerIndex == randomInnerIndex { + selectedPost = post + break + } + innerIndex++ + } + + return selectedPost, nil +} diff --git a/loadtest/store/store.go b/loadtest/store/store.go index b5b108ad3..2bb539c7c 100644 --- a/loadtest/store/store.go +++ b/loadtest/store/store.go @@ -183,6 +183,7 @@ type MutableUserStore interface { // scheduled posts SetScheduledPost(teamId, id string, scheduledPost *model.ScheduledPost) error + GetRandomScheduledPost() (*model.ScheduledPost, error) // posts // SetPost stores the given post. diff --git a/loadtest/user/user.go b/loadtest/user/user.go index 6894a253f..2de482385 100644 --- a/loadtest/user/user.go +++ b/loadtest/user/user.go @@ -328,4 +328,6 @@ type User interface { // Scheduled Posts CreateScheduledPost(teamId string, scheduledPost *model.ScheduledPost) error + GetRandomScheduledPost() *model.ScheduledPost + UpdateScheduledPost(teamId string, scheduledPost *model.ScheduledPost) error } diff --git a/loadtest/user/userentity/scheduled_posts.go b/loadtest/user/userentity/scheduled_posts.go index a650f166b..f4883fd7a 100644 --- a/loadtest/user/userentity/scheduled_posts.go +++ b/loadtest/user/userentity/scheduled_posts.go @@ -29,3 +29,29 @@ func (ue *UserEntity) CreateScheduledPost(teamId string, scheduledPost *model.Sc return ue.store.SetScheduledPost(teamId, id, createdScheduledPost) } + +func (ue *UserEntity) UpdateScheduledPost(teamId string, scheduledPost *model.ScheduledPost) error { + user, err := ue.getUserFromStore() + if err != nil { + return err + } + + scheduledPost.UserId = user.Id + updatedScheduledPost, _, err := ue.client.UpdateScheduledPost(context.Background(), scheduledPost) + if err != nil { + return err + } + + id := scheduledPost.ChannelId + + if updatedScheduledPost.RootId != "" { + id = scheduledPost.RootId + } + + return ue.store.SetScheduledPost(teamId, id, updatedScheduledPost) + +} + +func (ue *UserEntity) GetRandomScheduledPost() *model.ScheduledPost { + return ue.GetRandomScheduledPost() +} From f51ece6daf07493d63ec18cc7b8b39291aa4bdfe Mon Sep 17 00:00:00 2001 From: Harshil Sharma Date: Mon, 28 Oct 2024 16:15:32 +0530 Subject: [PATCH 03/15] DeleteScheduledPost --- .../control/simulcontroller/controller.go | 6 +++ .../simulcontroller/scheduled_posts.go | 21 ++++++++- loadtest/store/memstore/random.go | 45 +++++++++++++++++++ loadtest/store/memstore/store.go | 45 ------------------- loadtest/store/store.go | 2 + loadtest/user/user.go | 2 +- loadtest/user/userentity/scheduled_posts.go | 5 ++- 7 files changed, 77 insertions(+), 49 deletions(-) diff --git a/loadtest/control/simulcontroller/controller.go b/loadtest/control/simulcontroller/controller.go index a6a29c754..0229c31a7 100644 --- a/loadtest/control/simulcontroller/controller.go +++ b/loadtest/control/simulcontroller/controller.go @@ -276,6 +276,12 @@ func getActionList(c *SimulController) []userAction { frequency: 0.006, minServerVersion: control.UnreleasedVersion, }, + { + name: "DeleteScheduledPost", + run: c.deleteScheduledPost, + frequency: 0.006, + minServerVersion: control.UnreleasedVersion, + }, // All actions are required to contain a valid minServerVersion: // - If the action is present in server versions equal or older than // control.MinSupportedVersion, use control.MinSupportedVersion. diff --git a/loadtest/control/simulcontroller/scheduled_posts.go b/loadtest/control/simulcontroller/scheduled_posts.go index 88c56cc1d..719b95c27 100644 --- a/loadtest/control/simulcontroller/scheduled_posts.go +++ b/loadtest/control/simulcontroller/scheduled_posts.go @@ -68,7 +68,10 @@ func (c *SimulController) createScheduledPost(u user.User) control.UserActionRes } func (c *SimulController) updateScheduledPost(u user.User) control.UserActionResponse { - scheduledPost := u.GetRandomScheduledPost() + scheduledPost, err := u.Store().GetRandomScheduledPost() + if err != nil { + return control.UserActionResponse{Err: control.NewUserError(err)} + } if scheduledPost == nil { return control.UserActionResponse{Info: "no scheduled posts found"} } @@ -92,3 +95,19 @@ func (c *SimulController) updateScheduledPost(u user.User) control.UserActionRes return control.UserActionResponse{Info: fmt.Sprintf("scheudled post updated in channel id %v", channel.Id)} } + +func (c *SimulController) deleteScheduledPost(u user.User) control.UserActionResponse { + scheduledPost, err := u.Store().GetRandomScheduledPost() + if err != nil { + return control.UserActionResponse{Err: control.NewUserError(err)} + } + if scheduledPost == nil { + return control.UserActionResponse{Info: "no scheduled posts found"} + } + + if err := u.DeleteScheduledPost(scheduledPost.Id); err != nil { + return control.UserActionResponse{Err: control.NewUserError(err)} + } + + return control.UserActionResponse{Info: fmt.Sprintf("scheudled post deleteted with id %v", scheduledPost.Id)} +} diff --git a/loadtest/store/memstore/random.go b/loadtest/store/memstore/random.go index 562b0f086..b97a383c9 100644 --- a/loadtest/store/memstore/random.go +++ b/loadtest/store/memstore/random.go @@ -6,6 +6,7 @@ package memstore import ( "errors" "math/rand" + "time" "github.com/mattermost/mattermost-load-test-ng/loadtest/store" "github.com/mattermost/mattermost/server/public/model" @@ -448,3 +449,47 @@ func (s *MemStore) RandomDraftForTeam(teamId string) (string, error) { return draftIDs[rand.Intn(len(draftIDs))], nil } + +func (s *MemStore) GetRandomScheduledPost() (*model.ScheduledPost, error) { + s.lock.RLock() + defer s.lock.RUnlock() + + // Seed the random generator + rand.Seed(time.Now().UnixNano()) + + // Check if scheduledPosts is empty + if len(s.scheduledPosts) == 0 { + return nil, errors.New("no scheduled posts available") + } + + // Pick a random index for the outer map + randomOuterIndex := rand.Intn(len(s.scheduledPosts)) + var selectedInnerMap map[string]*model.ScheduledPost + outerIndex := 0 + for _, innerMap := range s.scheduledPosts { + if outerIndex == randomOuterIndex { + selectedInnerMap = innerMap + break + } + outerIndex++ + } + + // Check if the selected inner map is empty + if len(selectedInnerMap) == 0 { + return nil, errors.New("no posts available in selected category") + } + + // Pick a random index for the inner map + randomInnerIndex := rand.Intn(len(selectedInnerMap)) + var selectedPost *model.ScheduledPost + innerIndex := 0 + for _, post := range selectedInnerMap { + if innerIndex == randomInnerIndex { + selectedPost = post + break + } + innerIndex++ + } + + return selectedPost, nil +} diff --git a/loadtest/store/memstore/store.go b/loadtest/store/memstore/store.go index 051200584..52e9673b8 100644 --- a/loadtest/store/memstore/store.go +++ b/loadtest/store/memstore/store.go @@ -6,7 +6,6 @@ package memstore import ( "errors" "fmt" - "math/rand" "sort" "strconv" "strings" @@ -1239,47 +1238,3 @@ func (s *MemStore) SetScheduledPost(teamId, id string, scheduledPost *model.Sche s.scheduledPosts[teamId][id] = scheduledPost return nil } - -func (s *MemStore) GetRandomScheduledPost() (*model.ScheduledPost, error) { - s.lock.RLock() - defer s.lock.RUnlock() - - // Seed the random generator - rand.Seed(time.Now().UnixNano()) - - // Check if scheduledPosts is empty - if len(s.scheduledPosts) == 0 { - return nil, errors.New("no scheduled posts available") - } - - // Pick a random index for the outer map - randomOuterIndex := rand.Intn(len(s.scheduledPosts)) - var selectedInnerMap map[string]*model.ScheduledPost - outerIndex := 0 - for _, innerMap := range s.scheduledPosts { - if outerIndex == randomOuterIndex { - selectedInnerMap = innerMap - break - } - outerIndex++ - } - - // Check if the selected inner map is empty - if len(selectedInnerMap) == 0 { - return nil, errors.New("no posts available in selected category") - } - - // Pick a random index for the inner map - randomInnerIndex := rand.Intn(len(selectedInnerMap)) - var selectedPost *model.ScheduledPost - innerIndex := 0 - for _, post := range selectedInnerMap { - if innerIndex == randomInnerIndex { - selectedPost = post - break - } - innerIndex++ - } - - return selectedPost, nil -} diff --git a/loadtest/store/store.go b/loadtest/store/store.go index 2bb539c7c..6ab2bcc10 100644 --- a/loadtest/store/store.go +++ b/loadtest/store/store.go @@ -146,6 +146,8 @@ type UserStore interface { // PostsWithAckRequests returns IDs of the posts that asked for acknowledgment. PostsWithAckRequests() ([]string, error) + + GetRandomScheduledPost() (*model.ScheduledPost, error) } // MutableUserStore is a super-set of UserStore which, apart from providing diff --git a/loadtest/user/user.go b/loadtest/user/user.go index 2de482385..13b23a59a 100644 --- a/loadtest/user/user.go +++ b/loadtest/user/user.go @@ -328,6 +328,6 @@ type User interface { // Scheduled Posts CreateScheduledPost(teamId string, scheduledPost *model.ScheduledPost) error - GetRandomScheduledPost() *model.ScheduledPost UpdateScheduledPost(teamId string, scheduledPost *model.ScheduledPost) error + DeleteScheduledPost(scheduledPostId string) error } diff --git a/loadtest/user/userentity/scheduled_posts.go b/loadtest/user/userentity/scheduled_posts.go index f4883fd7a..2ab058a87 100644 --- a/loadtest/user/userentity/scheduled_posts.go +++ b/loadtest/user/userentity/scheduled_posts.go @@ -52,6 +52,7 @@ func (ue *UserEntity) UpdateScheduledPost(teamId string, scheduledPost *model.Sc } -func (ue *UserEntity) GetRandomScheduledPost() *model.ScheduledPost { - return ue.GetRandomScheduledPost() +func (ue *UserEntity) DeleteScheduledPost(scheduledPostId string) error { + _, _, err := ue.client.DeleteScheduledPost(context.Background(), scheduledPostId) + return err } From 28a8187e5b3b1f526e7ef4a5e39fa7cbce7e06b9 Mon Sep 17 00:00:00 2001 From: Harshil Sharma Date: Mon, 28 Oct 2024 16:27:39 +0530 Subject: [PATCH 04/15] SendScheduledPost --- .../control/simulcontroller/controller.go | 6 +++++ .../simulcontroller/scheduled_posts.go | 25 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/loadtest/control/simulcontroller/controller.go b/loadtest/control/simulcontroller/controller.go index 0229c31a7..8ac2b02b7 100644 --- a/loadtest/control/simulcontroller/controller.go +++ b/loadtest/control/simulcontroller/controller.go @@ -282,6 +282,12 @@ func getActionList(c *SimulController) []userAction { frequency: 0.006, minServerVersion: control.UnreleasedVersion, }, + { + name: "SendScheduledPost", + run: c.sendScheduledPost, + frequency: 0.006, + minServerVersion: control.UnreleasedVersion, + }, // All actions are required to contain a valid minServerVersion: // - If the action is present in server versions equal or older than // control.MinSupportedVersion, use control.MinSupportedVersion. diff --git a/loadtest/control/simulcontroller/scheduled_posts.go b/loadtest/control/simulcontroller/scheduled_posts.go index 719b95c27..7d58ae506 100644 --- a/loadtest/control/simulcontroller/scheduled_posts.go +++ b/loadtest/control/simulcontroller/scheduled_posts.go @@ -111,3 +111,28 @@ func (c *SimulController) deleteScheduledPost(u user.User) control.UserActionRes return control.UserActionResponse{Info: fmt.Sprintf("scheudled post deleteted with id %v", scheduledPost.Id)} } + +func (c *SimulController) sendScheduledPost(u user.User) control.UserActionResponse { + scheduledPost, err := u.Store().GetRandomScheduledPost() + if err != nil { + return control.UserActionResponse{Err: control.NewUserError(err)} + } + if scheduledPost == nil { + return control.UserActionResponse{Info: "no scheduled posts found"} + } + + post, err := scheduledPost.ToPost() + if err != nil { + return control.UserActionResponse{Err: control.NewUserError(err)} + } + + if _, err := u.CreatePost(post); err != nil { + return control.UserActionResponse{Err: control.NewUserError(err)} + } + + if err := u.DeleteScheduledPost(scheduledPost.Id); err != nil { + return control.UserActionResponse{Err: control.NewUserError(err)} + } + + return control.UserActionResponse{Info: fmt.Sprintf("scheudled post sent with id %v", scheduledPost.Id)} +} From 18fd0763dfc9e365ee8c063a45870835cd2a38fd Mon Sep 17 00:00:00 2001 From: Harshil Sharma Date: Tue, 29 Oct 2024 11:36:02 +0530 Subject: [PATCH 05/15] Updated loadTeam --- loadtest/control/simulcontroller/actions.go | 4 ++++ loadtest/user/user.go | 1 + loadtest/user/userentity/scheduled_posts.go | 15 +++++++++++++++ 3 files changed, 20 insertions(+) diff --git a/loadtest/control/simulcontroller/actions.go b/loadtest/control/simulcontroller/actions.go index 19056559a..709e98466 100644 --- a/loadtest/control/simulcontroller/actions.go +++ b/loadtest/control/simulcontroller/actions.go @@ -277,6 +277,10 @@ func loadTeam(u user.User, team *model.Team, gqlEnabled bool) control.UserAction return control.UserActionResponse{Err: control.NewUserError(err)} } + if err := u.GetTeamScheduledPosts(team.Id); err != nil { + return control.UserActionResponse{Err: control.NewUserError(err)} + } + return control.UserActionResponse{Info: fmt.Sprintf("loaded team %s", team.Id)} } diff --git a/loadtest/user/user.go b/loadtest/user/user.go index 13b23a59a..d6f8082e2 100644 --- a/loadtest/user/user.go +++ b/loadtest/user/user.go @@ -330,4 +330,5 @@ type User interface { CreateScheduledPost(teamId string, scheduledPost *model.ScheduledPost) error UpdateScheduledPost(teamId string, scheduledPost *model.ScheduledPost) error DeleteScheduledPost(scheduledPostId string) error + GetTeamScheduledPosts(teamID string) error } diff --git a/loadtest/user/userentity/scheduled_posts.go b/loadtest/user/userentity/scheduled_posts.go index 2ab058a87..95e8e75e4 100644 --- a/loadtest/user/userentity/scheduled_posts.go +++ b/loadtest/user/userentity/scheduled_posts.go @@ -36,6 +36,8 @@ func (ue *UserEntity) UpdateScheduledPost(teamId string, scheduledPost *model.Sc return err } + user.s + scheduledPost.UserId = user.Id updatedScheduledPost, _, err := ue.client.UpdateScheduledPost(context.Background(), scheduledPost) if err != nil { @@ -56,3 +58,16 @@ func (ue *UserEntity) DeleteScheduledPost(scheduledPostId string) error { _, _, err := ue.client.DeleteScheduledPost(context.Background(), scheduledPostId) return err } + +func (ue *UserEntity) GetTeamScheduledPosts(teamID string) error { + scheduledPosts, _, err := ue.client.GetUserScheduledPosts(context.Background(), teamID, true) + if err != nil { + return err + } + + for _, scheduledPost := range scheduledPosts { + _ = ue.store.SetScheduledPost(teamID, scheduledPost.Id, scheduledPost) + } + + return nil +} From 1e816dfd11b05ee52c261b5464080231fbc8e6d8 Mon Sep 17 00:00:00 2001 From: Harshil Sharma Date: Tue, 29 Oct 2024 14:13:22 +0530 Subject: [PATCH 06/15] WIP --- api/agent_client_test.go | 2 +- cmd/ltctl/collect.go | 2 +- deployment/terraform/cloudwatchlogs.go | 4 ++-- deployment/terraform/create.go | 6 +++--- go.mod | 5 +++-- go.sum | 10 ++++++---- go.work | 1 + loadtest/control/actions.go | 10 +++++----- loadtest/control/gencontroller/actions.go | 6 +++--- loadtest/control/simulcontroller/actions.go | 6 +++--- loadtest/store/memstore/store_test.go | 4 ++-- loadtest/user/userentity/actions.go | 2 +- loadtest/user/userentity/scheduled_posts.go | 2 -- loadtest/user/userentity/utils.go | 14 +++++++------- logger/logger.go | 8 ++++---- 15 files changed, 42 insertions(+), 40 deletions(-) diff --git a/api/agent_client_test.go b/api/agent_client_test.go index d1132df2b..067f94cff 100644 --- a/api/agent_client_test.go +++ b/api/agent_client_test.go @@ -33,7 +33,7 @@ func createFakeMMServer() *httptest.Server { case "/api/v4/config": mmCfg := model.Config{} mmCfg.SetDefaults() - mmCfg.TeamSettings.MaxUsersPerTeam = model.NewInt(10000) + mmCfg.TeamSettings.MaxUsersPerTeam = model.NewPointer(10000) json.NewEncoder(w).Encode(mmCfg) case "/api/v4/emoji": json.NewEncoder(w).Encode(&model.Emoji{}) diff --git a/cmd/ltctl/collect.go b/cmd/ltctl/collect.go index 0bd6a8f77..e65921f94 100644 --- a/cmd/ltctl/collect.go +++ b/cmd/ltctl/collect.go @@ -220,7 +220,7 @@ func collect(config deployment.Config, deploymentId string, outputName string) e if err := json.Unmarshal(input, &cfg); err != nil { return nil, fmt.Errorf("failed to unmarshal MM configuration: %w", err) } - cfg.Sanitize() + cfg.Sanitize([]*model.Manifest{}) sanitizedCfg, err := json.MarshalIndent(cfg, "", " ") if err != nil { return nil, fmt.Errorf("failed to sanitize MM configuration: %w", err) diff --git a/deployment/terraform/cloudwatchlogs.go b/deployment/terraform/cloudwatchlogs.go index dd79d351f..25052dbd4 100644 --- a/deployment/terraform/cloudwatchlogs.go +++ b/deployment/terraform/cloudwatchlogs.go @@ -136,8 +136,8 @@ func (t *Terraform) createCloudWatchLogsPolicy() error { docJsonStr := string(docJsonBytes) input := cloudwatchlogs.PutResourcePolicyInput{ - PolicyName: model.NewString("lt-cloudwatch-log-policy"), - PolicyDocument: model.NewString(docJsonStr), + PolicyName: model.NewPointer("lt-cloudwatch-log-policy"), + PolicyDocument: model.NewPointer(docJsonStr), } if _, err := cwclient.PutResourcePolicy(context.Background(), &input); err != nil { return fmt.Errorf("failed to create CloudWatchLogs policy; it can be manually created by running `aws logs put-resource-policy --policy-name lt-cloudwatch-log-policy --policy-document %q`; the next `deployment create` should work when such a policy is present in the AWS account; original error: %w", docJsonStr, err) diff --git a/deployment/terraform/create.go b/deployment/terraform/create.go index dc3f02c42..bff3c3556 100644 --- a/deployment/terraform/create.go +++ b/deployment/terraform/create.go @@ -1066,10 +1066,10 @@ func (t *Terraform) updateAppConfig(siteURL string, sshc *ssh.Client, jobServerE } if t.output.HasRedis() { - cfg.CacheSettings.CacheType = model.NewString(model.CacheTypeRedis) + cfg.CacheSettings.CacheType = model.NewPointer(model.CacheTypeRedis) redisEndpoint := net.JoinHostPort(t.output.RedisServer.Address, strconv.Itoa(t.output.RedisServer.Port)) - cfg.CacheSettings.RedisAddress = model.NewString(redisEndpoint) - cfg.CacheSettings.RedisDB = model.NewInt(0) + cfg.CacheSettings.RedisAddress = model.NewPointer(redisEndpoint) + cfg.CacheSettings.RedisDB = model.NewPointer(0) } if t.config.MattermostConfigPatchFile != "" { diff --git a/go.mod b/go.mod index 5ad686c52..27af90052 100644 --- a/go.mod +++ b/go.mod @@ -144,9 +144,10 @@ require ( golang.org/x/sys v0.22.0 // indirect golang.org/x/text v0.16.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240725223205-93522f1f2a9f // indirect + google.golang.org/genproto v0.0.0-20240725223205-93522f1f2a9f // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240722135656-d784300faade // indirect google.golang.org/grpc v1.65.0 // indirect - google.golang.org/protobuf v1.34.2 // indirect + google.golang.org/protobuf v1.35.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect modernc.org/gc/v3 v3.0.0-20240722195230-4a140ff9c08e // indirect diff --git a/go.sum b/go.sum index 1b42ab622..55ca8405d 100644 --- a/go.sum +++ b/go.sum @@ -649,8 +649,10 @@ google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240725223205-93522f1f2a9f h1:RARaIm8pxYuxyNPbBQf5igT7XdOyCNtat1qAT2ZxjU4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240725223205-93522f1f2a9f/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/genproto v0.0.0-20240725223205-93522f1f2a9f h1:htT2I9bZvGm+110zq8bIErMX+WgBWxCzV3ChwbvnKnc= +google.golang.org/genproto v0.0.0-20240725223205-93522f1f2a9f/go.mod h1:Sk3mLpoDFTAp6R4OvlcUgaG4ISTspKeFsIAXMn9Bm4Y= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240722135656-d784300faade h1:oCRSWfwGXQsqlVdErcyTt4A93Y8fo0/9D4b1gnI++qo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240722135656-d784300faade/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -670,8 +672,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/go.work b/go.work index 1d9a0b608..595a14f3e 100644 --- a/go.work +++ b/go.work @@ -3,4 +3,5 @@ go 1.22.6 use ( . ../../go/src/github.com/mattermost/mattermost/server/public + ../../go/src/github.com/mattermost/mattermost/server ) diff --git a/loadtest/control/actions.go b/loadtest/control/actions.go index fdbe052f1..d88fc773f 100644 --- a/loadtest/control/actions.go +++ b/loadtest/control/actions.go @@ -255,8 +255,8 @@ func CreateAckPost(u user.User) UserActionResponse { CreateAt: time.Now().UnixMilli(), Metadata: &model.PostMetadata{ Priority: &model.PostPriority{ - Priority: model.NewString(model.PostPriorityUrgent), - RequestedAck: model.NewBool(true), + Priority: model.NewPointer(model.PostPriorityUrgent), + RequestedAck: model.NewPointer(true), }, }, }) @@ -346,9 +346,9 @@ func CreatePersistentNotificationPost(u user.User) UserActionResponse { CreateAt: time.Now().UnixMilli(), Metadata: &model.PostMetadata{ Priority: &model.PostPriority{ - Priority: model.NewString(model.PostPriorityUrgent), - RequestedAck: model.NewBool(false), - PersistentNotifications: model.NewBool(true), + Priority: model.NewPointer(model.PostPriorityUrgent), + RequestedAck: model.NewPointer(false), + PersistentNotifications: model.NewPointer(true), }, }, }) diff --git a/loadtest/control/gencontroller/actions.go b/loadtest/control/gencontroller/actions.go index c3bf4c503..b03767018 100644 --- a/loadtest/control/gencontroller/actions.go +++ b/loadtest/control/gencontroller/actions.go @@ -258,9 +258,9 @@ func (c *GenController) createPost(u user.User) (res control.UserActionResponse) if isUrgent { post.Metadata = &model.PostMetadata{} post.Metadata.Priority = &model.PostPriority{ - Priority: model.NewString("urgent"), - RequestedAck: model.NewBool(false), - PersistentNotifications: model.NewBool(false), + Priority: model.NewPointer("urgent"), + RequestedAck: model.NewPointer(false), + PersistentNotifications: model.NewPointer(false), } } diff --git a/loadtest/control/simulcontroller/actions.go b/loadtest/control/simulcontroller/actions.go index 709e98466..4b6fc7f5d 100644 --- a/loadtest/control/simulcontroller/actions.go +++ b/loadtest/control/simulcontroller/actions.go @@ -800,9 +800,9 @@ func (c *SimulController) createPost(u user.User) control.UserActionResponse { if isUrgent { post.Metadata = &model.PostMetadata{} post.Metadata.Priority = &model.PostPriority{ - Priority: model.NewString("urgent"), - RequestedAck: model.NewBool(false), - PersistentNotifications: model.NewBool(false), + Priority: model.NewPointer("urgent"), + RequestedAck: model.NewPointer(false), + PersistentNotifications: model.NewPointer(false), } } diff --git a/loadtest/store/memstore/store_test.go b/loadtest/store/memstore/store_test.go index 7599fb555..d1d54d63b 100644 --- a/loadtest/store/memstore/store_test.go +++ b/loadtest/store/memstore/store_test.go @@ -762,8 +762,8 @@ func TestPostsWithAckRequests(t *testing.T) { Message: "ack post", Metadata: &model.PostMetadata{ Priority: &model.PostPriority{ - Priority: model.NewString(model.PostPriorityUrgent), - RequestedAck: model.NewBool(true), + Priority: model.NewPointer(model.PostPriorityUrgent), + RequestedAck: model.NewPointer(true), }, }, } diff --git a/loadtest/user/userentity/actions.go b/loadtest/user/userentity/actions.go index ead4b9614..ffb09fb9b 100644 --- a/loadtest/user/userentity/actions.go +++ b/loadtest/user/userentity/actions.go @@ -1394,7 +1394,7 @@ func (ue *UserEntity) GetPostThreadWithOpts(threadId, etag string, opts model.Ge if postList == nil || len(postList.Posts) == 0 { return nil, false, nil } - return postList.Order, postList.HasNext, ue.store.SetPosts(postListToSlice(postList)) + return postList.Order, *postList.HasNext, ue.store.SetPosts(postListToSlice(postList)) } // MarkAllThreadsInTeamAsRead marks all threads in the given team as read diff --git a/loadtest/user/userentity/scheduled_posts.go b/loadtest/user/userentity/scheduled_posts.go index 95e8e75e4..0d06b9d88 100644 --- a/loadtest/user/userentity/scheduled_posts.go +++ b/loadtest/user/userentity/scheduled_posts.go @@ -36,8 +36,6 @@ func (ue *UserEntity) UpdateScheduledPost(teamId string, scheduledPost *model.Sc return err } - user.s - scheduledPost.UserId = user.Id updatedScheduledPost, _, err := ue.client.UpdateScheduledPost(context.Background(), scheduledPost) if err != nil { diff --git a/loadtest/user/userentity/utils.go b/loadtest/user/userentity/utils.go index 154ed3062..d9c17d784 100644 --- a/loadtest/user/userentity/utils.go +++ b/loadtest/user/userentity/utils.go @@ -126,13 +126,13 @@ func convertToTypedTeams(userID string, input []gqlTeamMember) ([]*model.Team, [ AllowOpenInvite: team.AllowOpenInvite, } if team.GroupConstrained != nil { - mTeam.GroupConstrained = model.NewBool(*team.GroupConstrained) + mTeam.GroupConstrained = model.NewPointer(*team.GroupConstrained) } if team.SchemeId != nil { - mTeam.SchemeId = model.NewString(*team.SchemeId) + mTeam.SchemeId = model.NewPointer(*team.SchemeId) } if team.PolicyId != nil { - mTeam.PolicyID = model.NewString(*team.PolicyId) + mTeam.PolicyID = model.NewPointer(*team.PolicyId) } teams = append(teams, mTeam) @@ -172,16 +172,16 @@ func convertToTypedChannels(input []gqlChannel) ([]*model.Channel, string) { Props: c.Props, } if c.SchemeID != nil { - ch.SchemeId = model.NewString(*c.SchemeID) + ch.SchemeId = model.NewPointer(*c.SchemeID) } if c.GroupConstrained != nil { - ch.GroupConstrained = model.NewBool(*c.GroupConstrained) + ch.GroupConstrained = model.NewPointer(*c.GroupConstrained) } if c.Shared != nil { - ch.Shared = model.NewBool(*c.Shared) + ch.Shared = model.NewPointer(*c.Shared) } if c.PolicyID != nil { - ch.PolicyID = model.NewString(*c.PolicyID) + ch.PolicyID = model.NewPointer(*c.PolicyID) } cursor = c.Cursor channels = append(channels, ch) diff --git a/logger/logger.go b/logger/logger.go index 6629f56e2..8bf0bd121 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -29,10 +29,10 @@ func New(logSettings *Settings) *mlog.Logger { cfg, _ := config.MloggerConfigFromLoggerConfig(&model.LogSettings{ EnableConsole: &logSettings.EnableConsole, ConsoleJson: &logSettings.ConsoleJson, - ConsoleLevel: model.NewString(strings.ToLower(logSettings.ConsoleLevel)), + ConsoleLevel: model.NewPointer(strings.ToLower(logSettings.ConsoleLevel)), EnableFile: &logSettings.EnableFile, FileJson: &logSettings.FileJson, - FileLevel: model.NewString(strings.ToLower(logSettings.FileLevel)), + FileLevel: model.NewPointer(strings.ToLower(logSettings.FileLevel)), FileLocation: &logSettings.FileLocation, EnableColor: &logSettings.EnableColor, }, nil, func(filename string) string { @@ -48,10 +48,10 @@ func Init(logSettings *Settings) { cfg, _ := config.MloggerConfigFromLoggerConfig(&model.LogSettings{ EnableConsole: &logSettings.EnableConsole, ConsoleJson: &logSettings.ConsoleJson, - ConsoleLevel: model.NewString(strings.ToLower(logSettings.ConsoleLevel)), + ConsoleLevel: model.NewPointer(strings.ToLower(logSettings.ConsoleLevel)), EnableFile: &logSettings.EnableFile, FileJson: &logSettings.FileJson, - FileLevel: model.NewString(strings.ToLower(logSettings.FileLevel)), + FileLevel: model.NewPointer(strings.ToLower(logSettings.FileLevel)), FileLocation: &logSettings.FileLocation, EnableColor: &logSettings.EnableColor, }, nil, func(filename string) string { From a89e45f275199f6ed7b751cffe2543c0b7f86511 Mon Sep 17 00:00:00 2001 From: Harshil Sharma Date: Wed, 30 Oct 2024 09:44:19 +0530 Subject: [PATCH 07/15] WIP --- loadtest/control/actions.go | 2 + .../control/simulcontroller/controller.go | 8 +-- .../simulcontroller/scheduled_posts.go | 45 ++++++++++++-- loadtest/user/userentity/scheduled_posts.go | 58 +++++++++++++++---- 4 files changed, 91 insertions(+), 22 deletions(-) diff --git a/loadtest/control/actions.go b/loadtest/control/actions.go index d88fc773f..1b78e6e3c 100644 --- a/loadtest/control/actions.go +++ b/loadtest/control/actions.go @@ -1035,9 +1035,11 @@ func DraftsEnabled(u user.User) (bool, UserActionResponse) { func ScheduledPostsEnabled(u user.User) (bool, UserActionResponse) { allow, err := strconv.ParseBool(u.Store().ClientConfig()["ScheduledPosts"]) if err != nil { + fmt.Println("Error parsing ScheduledPosts config", err) return false, UserActionResponse{Err: NewUserError(err)} } + fmt.Println("Scheduled posts is enabled or not: ", allow) return allow, UserActionResponse{} } diff --git a/loadtest/control/simulcontroller/controller.go b/loadtest/control/simulcontroller/controller.go index 8ac2b02b7..9dca531ca 100644 --- a/loadtest/control/simulcontroller/controller.go +++ b/loadtest/control/simulcontroller/controller.go @@ -267,25 +267,25 @@ func getActionList(c *SimulController) []userAction { { name: "CreateScheduledPost", run: c.createScheduledPost, - frequency: 0.05, + frequency: 3, minServerVersion: control.UnreleasedVersion, }, { name: "UpdateScheduledPost", run: c.updateScheduledPost, - frequency: 0.006, + frequency: 3, minServerVersion: control.UnreleasedVersion, }, { name: "DeleteScheduledPost", run: c.deleteScheduledPost, - frequency: 0.006, + frequency: 3, minServerVersion: control.UnreleasedVersion, }, { name: "SendScheduledPost", run: c.sendScheduledPost, - frequency: 0.006, + frequency: 3, minServerVersion: control.UnreleasedVersion, }, // All actions are required to contain a valid minServerVersion: diff --git a/loadtest/control/simulcontroller/scheduled_posts.go b/loadtest/control/simulcontroller/scheduled_posts.go index 7d58ae506..5f527ed6d 100644 --- a/loadtest/control/simulcontroller/scheduled_posts.go +++ b/loadtest/control/simulcontroller/scheduled_posts.go @@ -10,19 +10,26 @@ import ( ) func (c *SimulController) createScheduledPost(u user.User) control.UserActionResponse { + fmt.Println("createScheduledPost: start") + if ok, resp := control.ScheduledPostsEnabled(u); resp.Err != nil { + fmt.Println("createScheduledPost: ScheduledPostsEnabled error", resp.Err) return resp } else if !ok { + fmt.Println("createScheduledPost: ScheduledPosts not enabled") return control.UserActionResponse{Info: "scheduled posts not enabled"} } + fmt.Println("createScheduledPost: ScheduledPost is enabled") + channel, err := u.Store().CurrentChannel() if err != nil { + fmt.Println("createScheduledPost: CurrentChannel error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } + fmt.Println("createScheduledPost: got the channel", channel.Id) var rootId = "" - // Assuming 25% of the scheduled posts are in a thread if rand.Float64() < 0.25 { post, err := u.Store().RandomPostForChannel(channel.Id) if err == nil { @@ -35,11 +42,13 @@ func (c *SimulController) createScheduledPost(u user.User) control.UserActionRes } if err := sendTypingEventIfEnabled(u, channel.Id); err != nil { + fmt.Println("createScheduledPost: sendTypingEventIfEnabled error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } message, err := createMessage(u, channel, false) if err != nil { + fmt.Println("createScheduledPost: createMessage error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } @@ -53,36 +62,44 @@ func (c *SimulController) createScheduledPost(u user.User) control.UserActionRes ScheduledAt: loadtest.RandomFutureTime(17_28_00_000, 10), } - // 2% of the times post will have files attached. if rand.Float64() < 0.02 { if err := control.AttachFilesToDraft(u, &scheduledPost.Draft); err != nil { + fmt.Println("createScheduledPost: AttachFilesToDraft error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } } if err := u.CreateScheduledPost(channel.TeamId, scheduledPost); err != nil { + fmt.Println("createScheduledPost: CreateScheduledPost error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } - return control.UserActionResponse{Info: fmt.Sprintf("scheudled post created in channel id %v", channel.Id)} + fmt.Println("createScheduledPost: end") + return control.UserActionResponse{Info: fmt.Sprintf("scheduled post created in channel id %v", channel.Id)} } func (c *SimulController) updateScheduledPost(u user.User) control.UserActionResponse { + fmt.Println("updateScheduledPost: start") + scheduledPost, err := u.Store().GetRandomScheduledPost() if err != nil { + fmt.Println("updateScheduledPost: GetRandomScheduledPost error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } if scheduledPost == nil { + fmt.Println("updateScheduledPost: no scheduled posts found") return control.UserActionResponse{Info: "no scheduled posts found"} } channel, err := u.Store().CurrentChannel() if err != nil { + fmt.Println("updateScheduledPost: CurrentChannel error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } message, err := createMessage(u, channel, false) if err != nil { + fmt.Println("updateScheduledPost: createMessage error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } @@ -90,49 +107,65 @@ func (c *SimulController) updateScheduledPost(u user.User) control.UserActionRes scheduledPost.ScheduledAt = loadtest.RandomFutureTime(17_28_00_000, 10) if err := u.UpdateScheduledPost(channel.TeamId, scheduledPost); err != nil { + fmt.Println("updateScheduledPost: UpdateScheduledPost error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } - return control.UserActionResponse{Info: fmt.Sprintf("scheudled post updated in channel id %v", channel.Id)} + fmt.Println("updateScheduledPost: end") + return control.UserActionResponse{Info: fmt.Sprintf("scheduled post updated in channel id %v", channel.Id)} } func (c *SimulController) deleteScheduledPost(u user.User) control.UserActionResponse { + fmt.Println("deleteScheduledPost: start") + scheduledPost, err := u.Store().GetRandomScheduledPost() if err != nil { + fmt.Println("deleteScheduledPost: GetRandomScheduledPost error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } if scheduledPost == nil { + fmt.Println("deleteScheduledPost: no scheduled posts found") return control.UserActionResponse{Info: "no scheduled posts found"} } if err := u.DeleteScheduledPost(scheduledPost.Id); err != nil { + fmt.Println("deleteScheduledPost: DeleteScheduledPost error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } - return control.UserActionResponse{Info: fmt.Sprintf("scheudled post deleteted with id %v", scheduledPost.Id)} + fmt.Println("deleteScheduledPost: end") + return control.UserActionResponse{Info: fmt.Sprintf("scheduled post deleted with id %v", scheduledPost.Id)} } func (c *SimulController) sendScheduledPost(u user.User) control.UserActionResponse { + fmt.Println("sendScheduledPost: start") + scheduledPost, err := u.Store().GetRandomScheduledPost() if err != nil { + fmt.Println("sendScheduledPost: GetRandomScheduledPost error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } if scheduledPost == nil { + fmt.Println("sendScheduledPost: no scheduled posts found") return control.UserActionResponse{Info: "no scheduled posts found"} } post, err := scheduledPost.ToPost() if err != nil { + fmt.Println("sendScheduledPost: ToPost error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } if _, err := u.CreatePost(post); err != nil { + fmt.Println("sendScheduledPost: CreatePost error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } if err := u.DeleteScheduledPost(scheduledPost.Id); err != nil { + fmt.Println("sendScheduledPost: DeleteScheduledPost error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } - return control.UserActionResponse{Info: fmt.Sprintf("scheudled post sent with id %v", scheduledPost.Id)} + fmt.Println("sendScheduledPost: end") + return control.UserActionResponse{Info: fmt.Sprintf("scheduled post sent with id %v", scheduledPost.Id)} } diff --git a/loadtest/user/userentity/scheduled_posts.go b/loadtest/user/userentity/scheduled_posts.go index 0d06b9d88..3045cd9da 100644 --- a/loadtest/user/userentity/scheduled_posts.go +++ b/loadtest/user/userentity/scheduled_posts.go @@ -1,71 +1,105 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - package userentity import ( "context" + "fmt" "github.com/mattermost/mattermost/server/public/model" ) func (ue *UserEntity) CreateScheduledPost(teamId string, scheduledPost *model.ScheduledPost) error { + fmt.Println("CreateScheduledPost: start") + user, err := ue.getUserFromStore() if err != nil { + fmt.Println("CreateScheduledPost: getUserFromStore error", err) return err } scheduledPost.UserId = user.Id createdScheduledPost, _, err := ue.client.CreateScheduledPost(context.Background(), scheduledPost) if err != nil { + fmt.Println("CreateScheduledPost: CreateScheduledPost error", err) return err } id := scheduledPost.ChannelId - if createdScheduledPost.RootId != "" { id = scheduledPost.RootId } - return ue.store.SetScheduledPost(teamId, id, createdScheduledPost) + err = ue.store.SetScheduledPost(teamId, id, createdScheduledPost) + if err != nil { + fmt.Println("CreateScheduledPost: SetScheduledPost error", err) + return err + } + fmt.Println("CreateScheduledPost: end") + return nil } func (ue *UserEntity) UpdateScheduledPost(teamId string, scheduledPost *model.ScheduledPost) error { + fmt.Println("UpdateScheduledPost: start") + user, err := ue.getUserFromStore() if err != nil { + fmt.Println("UpdateScheduledPost: getUserFromStore error", err) return err } scheduledPost.UserId = user.Id updatedScheduledPost, _, err := ue.client.UpdateScheduledPost(context.Background(), scheduledPost) if err != nil { + fmt.Println("UpdateScheduledPost: UpdateScheduledPost error", err) return err } id := scheduledPost.ChannelId - if updatedScheduledPost.RootId != "" { - id = scheduledPost.RootId + id = updatedScheduledPost.RootId } - return ue.store.SetScheduledPost(teamId, id, updatedScheduledPost) + err = ue.store.SetScheduledPost(teamId, id, updatedScheduledPost) + if err != nil { + fmt.Println("UpdateScheduledPost: SetScheduledPost error", err) + return err + } + fmt.Println("UpdateScheduledPost: end") + return nil } func (ue *UserEntity) DeleteScheduledPost(scheduledPostId string) error { + fmt.Println("DeleteScheduledPost: start") + _, _, err := ue.client.DeleteScheduledPost(context.Background(), scheduledPostId) - return err + if err != nil { + fmt.Println("DeleteScheduledPost: DeleteScheduledPost error", err) + return err + } + + fmt.Println("DeleteScheduledPost: end") + return nil } func (ue *UserEntity) GetTeamScheduledPosts(teamID string) error { - scheduledPosts, _, err := ue.client.GetUserScheduledPosts(context.Background(), teamID, true) + fmt.Println("GetTeamScheduledPosts: start") + + scheduledPostsByTeam, _, err := ue.client.GetUserScheduledPosts(context.Background(), teamID, true) if err != nil { + fmt.Println("GetTeamScheduledPosts: GetUserScheduledPosts error", err) return err } - for _, scheduledPost := range scheduledPosts { - _ = ue.store.SetScheduledPost(teamID, scheduledPost.Id, scheduledPost) + for teamIdInResponse := range scheduledPostsByTeam { + for _, scheduledPost := range scheduledPostsByTeam[teamIdInResponse] { + err := ue.store.SetScheduledPost(teamID, scheduledPost.Id, scheduledPost) + if err != nil { + fmt.Println("GetTeamScheduledPosts: SetScheduledPost error", err) + return err + } + } } + fmt.Println("GetTeamScheduledPosts: end") return nil } From 532675b02d9cb39b163f31191bed43f7c14e6460 Mon Sep 17 00:00:00 2001 From: Harshil Sharma Date: Mon, 4 Nov 2024 12:44:50 +0530 Subject: [PATCH 08/15] WIP --- loadtest/control/simulcontroller/actions.go | 6 +-- .../control/simulcontroller/controller.go | 48 +++++++++---------- .../simulcontroller/scheduled_posts.go | 4 ++ loadtest/store/memstore/random.go | 23 +++++++++ loadtest/store/memstore/store.go | 4 ++ loadtest/store/store.go | 2 + loadtest/user/userentity/scheduled_posts.go | 2 + 7 files changed, 62 insertions(+), 27 deletions(-) diff --git a/loadtest/control/simulcontroller/actions.go b/loadtest/control/simulcontroller/actions.go index 4b6fc7f5d..e93bd397d 100644 --- a/loadtest/control/simulcontroller/actions.go +++ b/loadtest/control/simulcontroller/actions.go @@ -277,9 +277,9 @@ func loadTeam(u user.User, team *model.Team, gqlEnabled bool) control.UserAction return control.UserActionResponse{Err: control.NewUserError(err)} } - if err := u.GetTeamScheduledPosts(team.Id); err != nil { - return control.UserActionResponse{Err: control.NewUserError(err)} - } + //if err := u.GetTeamScheduledPosts(team.Id); err != nil { + // return control.UserActionResponse{Err: control.NewUserError(err)} + //} return control.UserActionResponse{Info: fmt.Sprintf("loaded team %s", team.Id)} } diff --git a/loadtest/control/simulcontroller/controller.go b/loadtest/control/simulcontroller/controller.go index 9dca531ca..2f21f097f 100644 --- a/loadtest/control/simulcontroller/controller.go +++ b/loadtest/control/simulcontroller/controller.go @@ -264,30 +264,30 @@ func getActionList(c *SimulController) []userAction { frequency: 1.41, minServerVersion: control.MinSupportedVersion, // 7.7.0 }, - { - name: "CreateScheduledPost", - run: c.createScheduledPost, - frequency: 3, - minServerVersion: control.UnreleasedVersion, - }, - { - name: "UpdateScheduledPost", - run: c.updateScheduledPost, - frequency: 3, - minServerVersion: control.UnreleasedVersion, - }, - { - name: "DeleteScheduledPost", - run: c.deleteScheduledPost, - frequency: 3, - minServerVersion: control.UnreleasedVersion, - }, - { - name: "SendScheduledPost", - run: c.sendScheduledPost, - frequency: 3, - minServerVersion: control.UnreleasedVersion, - }, + //{ + // name: "CreateScheduledPost", + // run: c.createScheduledPost, + // frequency: 0.2, + // minServerVersion: control.MinSupportedVersion, + //}, + //{ + // name: "UpdateScheduledPost", + // run: c.updateScheduledPost, + // frequency: 0.1, + // minServerVersion: control.MinSupportedVersion, + //}, + //{ + // name: "DeleteScheduledPost", + // run: c.deleteScheduledPost, + // frequency: 0.1, + // minServerVersion: control.MinSupportedVersion, + //}, + //{ + // name: "SendScheduledPost", + // run: c.sendScheduledPost, + // frequency: 0.1, + // minServerVersion: control.MinSupportedVersion, + //}, // All actions are required to contain a valid minServerVersion: // - If the action is present in server versions equal or older than // control.MinSupportedVersion, use control.MinSupportedVersion. diff --git a/loadtest/control/simulcontroller/scheduled_posts.go b/loadtest/control/simulcontroller/scheduled_posts.go index 5f527ed6d..2314dc0a0 100644 --- a/loadtest/control/simulcontroller/scheduled_posts.go +++ b/loadtest/control/simulcontroller/scheduled_posts.go @@ -133,6 +133,8 @@ func (c *SimulController) deleteScheduledPost(u user.User) control.UserActionRes return control.UserActionResponse{Err: control.NewUserError(err)} } + u.Store().DeleteScheduledPost(scheduledPost.Id) + fmt.Println("deleteScheduledPost: end") return control.UserActionResponse{Info: fmt.Sprintf("scheduled post deleted with id %v", scheduledPost.Id)} } @@ -166,6 +168,8 @@ func (c *SimulController) sendScheduledPost(u user.User) control.UserActionRespo return control.UserActionResponse{Err: control.NewUserError(err)} } + u.Store().DeleteScheduledPost(scheduledPost.Id) + fmt.Println("sendScheduledPost: end") return control.UserActionResponse{Info: fmt.Sprintf("scheduled post sent with id %v", scheduledPost.Id)} } diff --git a/loadtest/store/memstore/random.go b/loadtest/store/memstore/random.go index b97a383c9..5c8a36ea3 100644 --- a/loadtest/store/memstore/random.go +++ b/loadtest/store/memstore/random.go @@ -493,3 +493,26 @@ func (s *MemStore) GetRandomScheduledPost() (*model.ScheduledPost, error) { return selectedPost, nil } + +func (s *MemStore) DeleteScheduledPost(scheduledPostID string) { + s.lock.Lock() + defer s.lock.Unlock() + + for teamId := range s.scheduledPosts { + if _, ok := s.scheduledPosts[teamId][scheduledPostID]; ok { + delete(s.scheduledPosts[teamId], scheduledPostID) + break + } + } +} + +func (s *MemStore) UpdateScheduledPost(teamId string, scheduledPost *model.ScheduledPost) { + s.lock.Lock() + defer s.lock.Unlock() + + if _, ok := s.scheduledPosts[teamId]; !ok { + s.scheduledPosts[teamId] = make(map[string]*model.ScheduledPost) + } + + s.scheduledPosts[teamId][scheduledPost.Id] = scheduledPost +} diff --git a/loadtest/store/memstore/store.go b/loadtest/store/memstore/store.go index 52e9673b8..4bcf31d2e 100644 --- a/loadtest/store/memstore/store.go +++ b/loadtest/store/memstore/store.go @@ -1231,6 +1231,10 @@ func (s *MemStore) SetScheduledPost(teamId, id string, scheduledPost *model.Sche return errors.New("memstore: scheduled post should not be nil") } + if s.scheduledPosts == nil { + s.scheduledPosts = map[string]map[string]*model.ScheduledPost{} + } + if s.scheduledPosts[teamId] == nil { s.scheduledPosts[teamId] = map[string]*model.ScheduledPost{} } diff --git a/loadtest/store/store.go b/loadtest/store/store.go index 6ab2bcc10..9d57148e8 100644 --- a/loadtest/store/store.go +++ b/loadtest/store/store.go @@ -148,6 +148,8 @@ type UserStore interface { PostsWithAckRequests() ([]string, error) GetRandomScheduledPost() (*model.ScheduledPost, error) + DeleteScheduledPost(scheduledPostID string) + UpdateScheduledPost(teamId string, scheduledPost *model.ScheduledPost) } // MutableUserStore is a super-set of UserStore which, apart from providing diff --git a/loadtest/user/userentity/scheduled_posts.go b/loadtest/user/userentity/scheduled_posts.go index 3045cd9da..09829fc9a 100644 --- a/loadtest/user/userentity/scheduled_posts.go +++ b/loadtest/user/userentity/scheduled_posts.go @@ -64,6 +64,8 @@ func (ue *UserEntity) UpdateScheduledPost(teamId string, scheduledPost *model.Sc return err } + ue.Store().UpdateScheduledPost(teamId, updatedScheduledPost) + fmt.Println("UpdateScheduledPost: end") return nil } From 639448693bced4f54f2c0a895577d0d4ef80b29c Mon Sep 17 00:00:00 2001 From: Harshil Sharma Date: Thu, 14 Nov 2024 12:17:01 +0530 Subject: [PATCH 09/15] Cleanup --- go.work | 7 ------- loadtest/control/actions.go | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) delete mode 100644 go.work diff --git a/go.work b/go.work deleted file mode 100644 index 595a14f3e..000000000 --- a/go.work +++ /dev/null @@ -1,7 +0,0 @@ -go 1.22.6 - -use ( - . - ../../go/src/github.com/mattermost/mattermost/server/public - ../../go/src/github.com/mattermost/mattermost/server -) diff --git a/loadtest/control/actions.go b/loadtest/control/actions.go index 2398d8d64..21546d4b5 100644 --- a/loadtest/control/actions.go +++ b/loadtest/control/actions.go @@ -1044,7 +1044,7 @@ func ScheduledPostsEnabled(u user.User) (bool, UserActionResponse) { return false, UserActionResponse{Err: NewUserError(err)} } - fmt.Println("Scheduled posts is enabled or not: ", allow) + return allow, UserActionResponse{} } // MessageExport simulates the given user performing From d37d54e75e2a1650a30f45901574460890a7e4f3 Mon Sep 17 00:00:00 2001 From: Harshil Sharma Date: Thu, 14 Nov 2024 12:26:09 +0530 Subject: [PATCH 10/15] Comment cleanup --- go.mod | 7 ++-- go.sum | 12 +++---- loadtest/control/simulcontroller/actions.go | 6 ++-- .../simulcontroller/scheduled_posts.go | 33 ++++++++++++------- loadtest/user/userentity/scheduled_posts.go | 3 -- 5 files changed, 33 insertions(+), 28 deletions(-) diff --git a/go.mod b/go.mod index 0545cf586..4ed67a5a9 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,7 @@ require ( github.com/gliderlabs/ssh v0.1.1 github.com/grafana/alloy/syntax v0.1.0 github.com/graph-gophers/graphql-go v1.5.1-0.20230110080634-edea822f558a - github.com/mattermost/mattermost/server/public v0.1.8-0.20241015185928-63c97f5a6d8f + github.com/mattermost/mattermost/server/public v0.1.9 github.com/mattermost/mattermost/server/v8 v8.0.0-20241015185928-63c97f5a6d8f github.com/opensearch-project/opensearch-go/v4 v4.1.0 github.com/pelletier/go-toml/v2 v2.2.2 @@ -144,10 +144,9 @@ require ( golang.org/x/sys v0.24.0 // indirect golang.org/x/text v0.16.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto v0.0.0-20240725223205-93522f1f2a9f // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240722135656-d784300faade // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240725223205-93522f1f2a9f // indirect google.golang.org/grpc v1.65.0 // indirect - google.golang.org/protobuf v1.35.1 // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect modernc.org/gc/v3 v3.0.0-20240722195230-4a140ff9c08e // indirect diff --git a/go.sum b/go.sum index d5b8cf5c1..562ad7c01 100644 --- a/go.sum +++ b/go.sum @@ -272,6 +272,8 @@ github.com/mattermost/logr/v2 v2.0.21 h1:CMHsP+nrbRlEC4g7BwOk1GAnMtHkniFhlSQPXy5 github.com/mattermost/logr/v2 v2.0.21/go.mod h1:kZkB/zqKL9e+RY5gB3vGpsyenC+TpuiOenjMkvJJbzc= github.com/mattermost/mattermost/server/public v0.1.8-0.20241015185928-63c97f5a6d8f h1:NUAf56HZHFLayAyCqHxeVLmxJUN9xw3Qxc9m3ghy+Xw= github.com/mattermost/mattermost/server/public v0.1.8-0.20241015185928-63c97f5a6d8f/go.mod h1:SkTKbMul91Rq0v2dIxe8mqzUOY+3KwlwwLmAlxDfGCk= +github.com/mattermost/mattermost/server/public v0.1.9 h1:l/OKPRVuFeqL0yqRVC/JpveG5sLNKcT9llxqMkO9e+s= +github.com/mattermost/mattermost/server/public v0.1.9/go.mod h1:SkTKbMul91Rq0v2dIxe8mqzUOY+3KwlwwLmAlxDfGCk= github.com/mattermost/mattermost/server/v8 v8.0.0-20241015185928-63c97f5a6d8f h1:h4T89Qkb3kddGnRN7xQAuB+fDaL3OgUgc5YPmssmzj8= github.com/mattermost/mattermost/server/v8 v8.0.0-20241015185928-63c97f5a6d8f/go.mod h1:zwMZYGK4/xDy/kyepVBqXhM58YMTCRlanv/uKrZzJdw= github.com/mattermost/morph v1.1.0 h1:Q9vrJbeM3s2jfweGheq12EFIzdNp9a/6IovcbvOQ6Cw= @@ -649,10 +651,8 @@ google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20240725223205-93522f1f2a9f h1:htT2I9bZvGm+110zq8bIErMX+WgBWxCzV3ChwbvnKnc= -google.golang.org/genproto v0.0.0-20240725223205-93522f1f2a9f/go.mod h1:Sk3mLpoDFTAp6R4OvlcUgaG4ISTspKeFsIAXMn9Bm4Y= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240722135656-d784300faade h1:oCRSWfwGXQsqlVdErcyTt4A93Y8fo0/9D4b1gnI++qo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240722135656-d784300faade/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240725223205-93522f1f2a9f h1:RARaIm8pxYuxyNPbBQf5igT7XdOyCNtat1qAT2ZxjU4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240725223205-93522f1f2a9f/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -672,8 +672,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= -google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/loadtest/control/simulcontroller/actions.go b/loadtest/control/simulcontroller/actions.go index ee70fa913..3248a4e36 100644 --- a/loadtest/control/simulcontroller/actions.go +++ b/loadtest/control/simulcontroller/actions.go @@ -293,9 +293,9 @@ func loadTeam(u user.User, team *model.Team, gqlEnabled bool) control.UserAction return control.UserActionResponse{Err: control.NewUserError(err)} } - //if err := u.GetTeamScheduledPosts(team.Id); err != nil { - // return control.UserActionResponse{Err: control.NewUserError(err)} - //} + if err := u.GetTeamScheduledPosts(team.Id); err != nil { + return control.UserActionResponse{Err: control.NewUserError(err)} + } return control.UserActionResponse{Info: fmt.Sprintf("loaded team %s", team.Id)} } diff --git a/loadtest/control/simulcontroller/scheduled_posts.go b/loadtest/control/simulcontroller/scheduled_posts.go index 2314dc0a0..02765da81 100644 --- a/loadtest/control/simulcontroller/scheduled_posts.go +++ b/loadtest/control/simulcontroller/scheduled_posts.go @@ -10,8 +10,6 @@ import ( ) func (c *SimulController) createScheduledPost(u user.User) control.UserActionResponse { - fmt.Println("createScheduledPost: start") - if ok, resp := control.ScheduledPostsEnabled(u); resp.Err != nil { fmt.Println("createScheduledPost: ScheduledPostsEnabled error", resp.Err) return resp @@ -20,8 +18,6 @@ func (c *SimulController) createScheduledPost(u user.User) control.UserActionRes return control.UserActionResponse{Info: "scheduled posts not enabled"} } - fmt.Println("createScheduledPost: ScheduledPost is enabled") - channel, err := u.Store().CurrentChannel() if err != nil { fmt.Println("createScheduledPost: CurrentChannel error", err) @@ -74,12 +70,17 @@ func (c *SimulController) createScheduledPost(u user.User) control.UserActionRes return control.UserActionResponse{Err: control.NewUserError(err)} } - fmt.Println("createScheduledPost: end") return control.UserActionResponse{Info: fmt.Sprintf("scheduled post created in channel id %v", channel.Id)} } func (c *SimulController) updateScheduledPost(u user.User) control.UserActionResponse { - fmt.Println("updateScheduledPost: start") + if ok, resp := control.ScheduledPostsEnabled(u); resp.Err != nil { + fmt.Println("updateScheduledPost: ScheduledPostsEnabled error", resp.Err) + return resp + } else if !ok { + fmt.Println("updateScheduledPost: ScheduledPosts not enabled") + return control.UserActionResponse{Info: "scheduled posts not enabled"} + } scheduledPost, err := u.Store().GetRandomScheduledPost() if err != nil { @@ -111,12 +112,17 @@ func (c *SimulController) updateScheduledPost(u user.User) control.UserActionRes return control.UserActionResponse{Err: control.NewUserError(err)} } - fmt.Println("updateScheduledPost: end") return control.UserActionResponse{Info: fmt.Sprintf("scheduled post updated in channel id %v", channel.Id)} } func (c *SimulController) deleteScheduledPost(u user.User) control.UserActionResponse { - fmt.Println("deleteScheduledPost: start") + if ok, resp := control.ScheduledPostsEnabled(u); resp.Err != nil { + fmt.Println("deleteScheduledPost: ScheduledPostsEnabled error", resp.Err) + return resp + } else if !ok { + fmt.Println("deleteScheduledPost: ScheduledPosts not enabled") + return control.UserActionResponse{Info: "scheduled posts not enabled"} + } scheduledPost, err := u.Store().GetRandomScheduledPost() if err != nil { @@ -134,13 +140,17 @@ func (c *SimulController) deleteScheduledPost(u user.User) control.UserActionRes } u.Store().DeleteScheduledPost(scheduledPost.Id) - - fmt.Println("deleteScheduledPost: end") return control.UserActionResponse{Info: fmt.Sprintf("scheduled post deleted with id %v", scheduledPost.Id)} } func (c *SimulController) sendScheduledPost(u user.User) control.UserActionResponse { - fmt.Println("sendScheduledPost: start") + if ok, resp := control.ScheduledPostsEnabled(u); resp.Err != nil { + fmt.Println("sendScheduledPost: ScheduledPostsEnabled error", resp.Err) + return resp + } else if !ok { + fmt.Println("sendScheduledPost: ScheduledPosts not enabled") + return control.UserActionResponse{Info: "scheduled posts not enabled"} + } scheduledPost, err := u.Store().GetRandomScheduledPost() if err != nil { @@ -170,6 +180,5 @@ func (c *SimulController) sendScheduledPost(u user.User) control.UserActionRespo u.Store().DeleteScheduledPost(scheduledPost.Id) - fmt.Println("sendScheduledPost: end") return control.UserActionResponse{Info: fmt.Sprintf("scheduled post sent with id %v", scheduledPost.Id)} } diff --git a/loadtest/user/userentity/scheduled_posts.go b/loadtest/user/userentity/scheduled_posts.go index 09829fc9a..56e530291 100644 --- a/loadtest/user/userentity/scheduled_posts.go +++ b/loadtest/user/userentity/scheduled_posts.go @@ -84,8 +84,6 @@ func (ue *UserEntity) DeleteScheduledPost(scheduledPostId string) error { } func (ue *UserEntity) GetTeamScheduledPosts(teamID string) error { - fmt.Println("GetTeamScheduledPosts: start") - scheduledPostsByTeam, _, err := ue.client.GetUserScheduledPosts(context.Background(), teamID, true) if err != nil { fmt.Println("GetTeamScheduledPosts: GetUserScheduledPosts error", err) @@ -102,6 +100,5 @@ func (ue *UserEntity) GetTeamScheduledPosts(teamID string) error { } } - fmt.Println("GetTeamScheduledPosts: end") return nil } From 2e439abcf98f84c4d09c880b06479ca08a204995 Mon Sep 17 00:00:00 2001 From: Harshil Sharma Date: Wed, 27 Nov 2024 09:59:50 +0530 Subject: [PATCH 11/15] review fixes --- .../control/simulcontroller/controller.go | 2 +- .../simulcontroller/scheduled_posts.go | 40 +++----------- loadtest/store/memstore/random.go | 52 ++++--------------- loadtest/store/memstore/store.go | 40 ++++++++++++-- loadtest/store/store.go | 2 +- loadtest/user/userentity/scheduled_posts.go | 36 ++----------- loadtest/utils.go | 2 +- 7 files changed, 58 insertions(+), 116 deletions(-) diff --git a/loadtest/control/simulcontroller/controller.go b/loadtest/control/simulcontroller/controller.go index 2b2ba25e2..a8eadcb56 100644 --- a/loadtest/control/simulcontroller/controller.go +++ b/loadtest/control/simulcontroller/controller.go @@ -308,7 +308,7 @@ func getActionList(c *SimulController) []userAction { }, { name: "SendScheduledPost", - run: c.sendScheduledPost, + run: c.sendScheduledPostNow, frequency: 0.1, minServerVersion: semver.MustParse("10.3.0"), }, diff --git a/loadtest/control/simulcontroller/scheduled_posts.go b/loadtest/control/simulcontroller/scheduled_posts.go index 02765da81..4d6edb6c6 100644 --- a/loadtest/control/simulcontroller/scheduled_posts.go +++ b/loadtest/control/simulcontroller/scheduled_posts.go @@ -9,22 +9,20 @@ import ( "math/rand" ) +const twoDaysInMilliseconds = 17_28_00_000 + func (c *SimulController) createScheduledPost(u user.User) control.UserActionResponse { if ok, resp := control.ScheduledPostsEnabled(u); resp.Err != nil { - fmt.Println("createScheduledPost: ScheduledPostsEnabled error", resp.Err) return resp } else if !ok { - fmt.Println("createScheduledPost: ScheduledPosts not enabled") return control.UserActionResponse{Info: "scheduled posts not enabled"} } channel, err := u.Store().CurrentChannel() if err != nil { - fmt.Println("createScheduledPost: CurrentChannel error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } - fmt.Println("createScheduledPost: got the channel", channel.Id) var rootId = "" if rand.Float64() < 0.25 { post, err := u.Store().RandomPostForChannel(channel.Id) @@ -38,13 +36,11 @@ func (c *SimulController) createScheduledPost(u user.User) control.UserActionRes } if err := sendTypingEventIfEnabled(u, channel.Id); err != nil { - fmt.Println("createScheduledPost: sendTypingEventIfEnabled error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } message, err := createMessage(u, channel, false) if err != nil { - fmt.Println("createScheduledPost: createMessage error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } @@ -55,18 +51,16 @@ func (c *SimulController) createScheduledPost(u user.User) control.UserActionRes RootId: rootId, CreateAt: model.GetMillis(), }, - ScheduledAt: loadtest.RandomFutureTime(17_28_00_000, 10), + ScheduledAt: loadtest.RandomFutureTime(twoDaysInMilliseconds, 10), } if rand.Float64() < 0.02 { if err := control.AttachFilesToDraft(u, &scheduledPost.Draft); err != nil { - fmt.Println("createScheduledPost: AttachFilesToDraft error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } } if err := u.CreateScheduledPost(channel.TeamId, scheduledPost); err != nil { - fmt.Println("createScheduledPost: CreateScheduledPost error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } @@ -75,40 +69,33 @@ func (c *SimulController) createScheduledPost(u user.User) control.UserActionRes func (c *SimulController) updateScheduledPost(u user.User) control.UserActionResponse { if ok, resp := control.ScheduledPostsEnabled(u); resp.Err != nil { - fmt.Println("updateScheduledPost: ScheduledPostsEnabled error", resp.Err) return resp } else if !ok { - fmt.Println("updateScheduledPost: ScheduledPosts not enabled") return control.UserActionResponse{Info: "scheduled posts not enabled"} } scheduledPost, err := u.Store().GetRandomScheduledPost() if err != nil { - fmt.Println("updateScheduledPost: GetRandomScheduledPost error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } if scheduledPost == nil { - fmt.Println("updateScheduledPost: no scheduled posts found") return control.UserActionResponse{Info: "no scheduled posts found"} } channel, err := u.Store().CurrentChannel() if err != nil { - fmt.Println("updateScheduledPost: CurrentChannel error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } message, err := createMessage(u, channel, false) if err != nil { - fmt.Println("updateScheduledPost: createMessage error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } scheduledPost.Message = message - scheduledPost.ScheduledAt = loadtest.RandomFutureTime(17_28_00_000, 10) + scheduledPost.ScheduledAt = loadtest.RandomFutureTime(twoDaysInMilliseconds, 10) if err := u.UpdateScheduledPost(channel.TeamId, scheduledPost); err != nil { - fmt.Println("updateScheduledPost: UpdateScheduledPost error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } @@ -117,68 +104,53 @@ func (c *SimulController) updateScheduledPost(u user.User) control.UserActionRes func (c *SimulController) deleteScheduledPost(u user.User) control.UserActionResponse { if ok, resp := control.ScheduledPostsEnabled(u); resp.Err != nil { - fmt.Println("deleteScheduledPost: ScheduledPostsEnabled error", resp.Err) return resp } else if !ok { - fmt.Println("deleteScheduledPost: ScheduledPosts not enabled") return control.UserActionResponse{Info: "scheduled posts not enabled"} } scheduledPost, err := u.Store().GetRandomScheduledPost() if err != nil { - fmt.Println("deleteScheduledPost: GetRandomScheduledPost error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } if scheduledPost == nil { - fmt.Println("deleteScheduledPost: no scheduled posts found") return control.UserActionResponse{Info: "no scheduled posts found"} } if err := u.DeleteScheduledPost(scheduledPost.Id); err != nil { - fmt.Println("deleteScheduledPost: DeleteScheduledPost error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } - u.Store().DeleteScheduledPost(scheduledPost.Id) return control.UserActionResponse{Info: fmt.Sprintf("scheduled post deleted with id %v", scheduledPost.Id)} } -func (c *SimulController) sendScheduledPost(u user.User) control.UserActionResponse { +func (c *SimulController) sendScheduledPostNow(u user.User) control.UserActionResponse { if ok, resp := control.ScheduledPostsEnabled(u); resp.Err != nil { - fmt.Println("sendScheduledPost: ScheduledPostsEnabled error", resp.Err) return resp } else if !ok { - fmt.Println("sendScheduledPost: ScheduledPosts not enabled") return control.UserActionResponse{Info: "scheduled posts not enabled"} } scheduledPost, err := u.Store().GetRandomScheduledPost() if err != nil { - fmt.Println("sendScheduledPost: GetRandomScheduledPost error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } if scheduledPost == nil { - fmt.Println("sendScheduledPost: no scheduled posts found") return control.UserActionResponse{Info: "no scheduled posts found"} } post, err := scheduledPost.ToPost() if err != nil { - fmt.Println("sendScheduledPost: ToPost error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } if _, err := u.CreatePost(post); err != nil { - fmt.Println("sendScheduledPost: CreatePost error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } if err := u.DeleteScheduledPost(scheduledPost.Id); err != nil { - fmt.Println("sendScheduledPost: DeleteScheduledPost error", err) return control.UserActionResponse{Err: control.NewUserError(err)} } - u.Store().DeleteScheduledPost(scheduledPost.Id) - - return control.UserActionResponse{Info: fmt.Sprintf("scheduled post sent with id %v", scheduledPost.Id)} + return control.UserActionResponse{Info: fmt.Sprintf("scheduled post with id %v manually sent now", scheduledPost.Id)} } diff --git a/loadtest/store/memstore/random.go b/loadtest/store/memstore/random.go index 5c8a36ea3..7a2bba2d2 100644 --- a/loadtest/store/memstore/random.go +++ b/loadtest/store/memstore/random.go @@ -5,11 +5,9 @@ package memstore import ( "errors" - "math/rand" - "time" - "github.com/mattermost/mattermost-load-test-ng/loadtest/store" "github.com/mattermost/mattermost/server/public/model" + "math/rand" ) var ( @@ -454,38 +452,31 @@ func (s *MemStore) GetRandomScheduledPost() (*model.ScheduledPost, error) { s.lock.RLock() defer s.lock.RUnlock() - // Seed the random generator - rand.Seed(time.Now().UnixNano()) - // Check if scheduledPosts is empty if len(s.scheduledPosts) == 0 { return nil, errors.New("no scheduled posts available") } - // Pick a random index for the outer map - randomOuterIndex := rand.Intn(len(s.scheduledPosts)) - var selectedInnerMap map[string]*model.ScheduledPost - outerIndex := 0 - for _, innerMap := range s.scheduledPosts { - if outerIndex == randomOuterIndex { - selectedInnerMap = innerMap - break + var keys []string + for key, innerMap := range s.scheduledPosts { + if len(innerMap) > 0 { + keys = append(keys, key) } - outerIndex++ } - // Check if the selected inner map is empty - if len(selectedInnerMap) == 0 { - return nil, errors.New("no posts available in selected category") + if len(keys) == 0 { + return nil, errors.New("no scheduled posts available") } + selectedInnerMap := s.scheduledPosts[keys[rand.Intn(len(keys))]] + // Pick a random index for the inner map randomInnerIndex := rand.Intn(len(selectedInnerMap)) var selectedPost *model.ScheduledPost innerIndex := 0 for _, post := range selectedInnerMap { if innerIndex == randomInnerIndex { - selectedPost = post + selectedPost = post[rand.Intn(len(post))] break } innerIndex++ @@ -493,26 +484,3 @@ func (s *MemStore) GetRandomScheduledPost() (*model.ScheduledPost, error) { return selectedPost, nil } - -func (s *MemStore) DeleteScheduledPost(scheduledPostID string) { - s.lock.Lock() - defer s.lock.Unlock() - - for teamId := range s.scheduledPosts { - if _, ok := s.scheduledPosts[teamId][scheduledPostID]; ok { - delete(s.scheduledPosts[teamId], scheduledPostID) - break - } - } -} - -func (s *MemStore) UpdateScheduledPost(teamId string, scheduledPost *model.ScheduledPost) { - s.lock.Lock() - defer s.lock.Unlock() - - if _, ok := s.scheduledPosts[teamId]; !ok { - s.scheduledPosts[teamId] = make(map[string]*model.ScheduledPost) - } - - s.scheduledPosts[teamId][scheduledPost.Id] = scheduledPost -} diff --git a/loadtest/store/memstore/store.go b/loadtest/store/memstore/store.go index 63377843d..9f7a5f9c7 100644 --- a/loadtest/store/memstore/store.go +++ b/loadtest/store/memstore/store.go @@ -52,7 +52,7 @@ type MemStore struct { featureFlags map[string]bool report *model.PerformanceReport channelBookmarks map[string]*model.ChannelBookmarkWithFileInfo - scheduledPosts map[string]map[string]*model.ScheduledPost + scheduledPosts map[string]map[string][]*model.ScheduledPost } // New returns a new instance of MemStore with the given config. @@ -131,6 +131,8 @@ func (s *MemStore) Clear() { s.drafts = map[string]map[string]*model.Draft{} clear(s.channelBookmarks) s.channelBookmarks = map[string]*model.ChannelBookmarkWithFileInfo{} + clear(s.scheduledPosts) + s.scheduledPosts = map[string]map[string][]*model.ScheduledPost{} } func (s *MemStore) setupQueues(config *Config) error { @@ -1360,7 +1362,7 @@ func (s *MemStore) DeleteChannelBookmark(bookmarkId string) error { return nil } -func (s *MemStore) SetScheduledPost(teamId, id string, scheduledPost *model.ScheduledPost) error { +func (s *MemStore) SetScheduledPost(teamId string, scheduledPost *model.ScheduledPost) error { s.lock.Lock() defer s.lock.Unlock() @@ -1369,13 +1371,41 @@ func (s *MemStore) SetScheduledPost(teamId, id string, scheduledPost *model.Sche } if s.scheduledPosts == nil { - s.scheduledPosts = map[string]map[string]*model.ScheduledPost{} + s.scheduledPosts = map[string]map[string][]*model.ScheduledPost{} } if s.scheduledPosts[teamId] == nil { - s.scheduledPosts[teamId] = map[string]*model.ScheduledPost{} + s.scheduledPosts[teamId] = map[string][]*model.ScheduledPost{} } - s.scheduledPosts[teamId][id] = scheduledPost + channelOrThreadId := scheduledPost.ChannelId + if scheduledPost.RootId != "" { + channelOrThreadId = scheduledPost.RootId + } + + s.scheduledPosts[teamId][channelOrThreadId] = append(s.scheduledPosts[teamId][channelOrThreadId], scheduledPost) return nil } + +func (s *MemStore) DeleteScheduledPost(scheduledPostID string) { + s.lock.Lock() + defer s.lock.Unlock() + + for teamId := range s.scheduledPosts { + if _, ok := s.scheduledPosts[teamId][scheduledPostID]; ok { + delete(s.scheduledPosts[teamId], scheduledPostID) + break + } + } +} + +func (s *MemStore) UpdateScheduledPost(teamId string, scheduledPost *model.ScheduledPost) { + s.lock.Lock() + defer s.lock.Unlock() + + if _, ok := s.scheduledPosts[teamId]; !ok { + s.scheduledPosts[teamId] = make(map[string][]*model.ScheduledPost) + } + + s.scheduledPosts[teamId][scheduledPost.Id] = append(s.scheduledPosts[teamId][scheduledPost.Id], scheduledPost) +} diff --git a/loadtest/store/store.go b/loadtest/store/store.go index c699cca5e..a713a9a42 100644 --- a/loadtest/store/store.go +++ b/loadtest/store/store.go @@ -205,7 +205,7 @@ type MutableUserStore interface { SetDrafts(teamId string, drafts []*model.Draft) error // scheduled posts - SetScheduledPost(teamId, id string, scheduledPost *model.ScheduledPost) error + SetScheduledPost(teamId string, scheduledPost *model.ScheduledPost) error GetRandomScheduledPost() (*model.ScheduledPost, error) // posts diff --git a/loadtest/user/userentity/scheduled_posts.go b/loadtest/user/userentity/scheduled_posts.go index 56e530291..0774208a3 100644 --- a/loadtest/user/userentity/scheduled_posts.go +++ b/loadtest/user/userentity/scheduled_posts.go @@ -2,99 +2,71 @@ package userentity import ( "context" - "fmt" "github.com/mattermost/mattermost/server/public/model" ) func (ue *UserEntity) CreateScheduledPost(teamId string, scheduledPost *model.ScheduledPost) error { - fmt.Println("CreateScheduledPost: start") - user, err := ue.getUserFromStore() if err != nil { - fmt.Println("CreateScheduledPost: getUserFromStore error", err) return err } scheduledPost.UserId = user.Id createdScheduledPost, _, err := ue.client.CreateScheduledPost(context.Background(), scheduledPost) if err != nil { - fmt.Println("CreateScheduledPost: CreateScheduledPost error", err) return err } - id := scheduledPost.ChannelId - if createdScheduledPost.RootId != "" { - id = scheduledPost.RootId - } - - err = ue.store.SetScheduledPost(teamId, id, createdScheduledPost) + err = ue.store.SetScheduledPost(teamId, createdScheduledPost) if err != nil { - fmt.Println("CreateScheduledPost: SetScheduledPost error", err) return err } - fmt.Println("CreateScheduledPost: end") return nil } func (ue *UserEntity) UpdateScheduledPost(teamId string, scheduledPost *model.ScheduledPost) error { - fmt.Println("UpdateScheduledPost: start") - user, err := ue.getUserFromStore() if err != nil { - fmt.Println("UpdateScheduledPost: getUserFromStore error", err) return err } scheduledPost.UserId = user.Id updatedScheduledPost, _, err := ue.client.UpdateScheduledPost(context.Background(), scheduledPost) if err != nil { - fmt.Println("UpdateScheduledPost: UpdateScheduledPost error", err) return err } - id := scheduledPost.ChannelId - if updatedScheduledPost.RootId != "" { - id = updatedScheduledPost.RootId - } - - err = ue.store.SetScheduledPost(teamId, id, updatedScheduledPost) + err = ue.store.SetScheduledPost(teamId, updatedScheduledPost) if err != nil { - fmt.Println("UpdateScheduledPost: SetScheduledPost error", err) return err } ue.Store().UpdateScheduledPost(teamId, updatedScheduledPost) - fmt.Println("UpdateScheduledPost: end") return nil } func (ue *UserEntity) DeleteScheduledPost(scheduledPostId string) error { - fmt.Println("DeleteScheduledPost: start") - _, _, err := ue.client.DeleteScheduledPost(context.Background(), scheduledPostId) if err != nil { - fmt.Println("DeleteScheduledPost: DeleteScheduledPost error", err) return err } - fmt.Println("DeleteScheduledPost: end") + ue.Store().DeleteScheduledPost(scheduledPostId) return nil } func (ue *UserEntity) GetTeamScheduledPosts(teamID string) error { scheduledPostsByTeam, _, err := ue.client.GetUserScheduledPosts(context.Background(), teamID, true) if err != nil { - fmt.Println("GetTeamScheduledPosts: GetUserScheduledPosts error", err) return err } for teamIdInResponse := range scheduledPostsByTeam { for _, scheduledPost := range scheduledPostsByTeam[teamIdInResponse] { - err := ue.store.SetScheduledPost(teamID, scheduledPost.Id, scheduledPost) + err := ue.store.SetScheduledPost(teamID, scheduledPost) if err != nil { - fmt.Println("GetTeamScheduledPosts: SetScheduledPost error", err) return err } } diff --git a/loadtest/utils.go b/loadtest/utils.go index deaa1c48a..e0f00cae1 100644 --- a/loadtest/utils.go +++ b/loadtest/utils.go @@ -90,7 +90,7 @@ func nextPowerOf2(val int) int { return val } -// RandomFutureTime generates a random time between (now + xMilliseconds) to (now + xDays) in Unix milliseconds. +// RandomFutureTime generates a random time between (now + millisecondsFromNow) to (now + uptoDaysFromNow) in Unix milliseconds. func RandomFutureTime(millisecondsFromNow int64, uptoDaysFromNow int) int64 { now := time.Now() minOffset := millisecondsFromNow // Minimum offset in milliseconds From 1e2606eb57ee9f1e034db8a7d006c70dcb312498 Mon Sep 17 00:00:00 2001 From: Harshil Sharma Date: Mon, 9 Dec 2024 08:22:33 +0530 Subject: [PATCH 12/15] Cleanup --- .../control/simulcontroller/scheduled_posts.go | 7 +++---- loadtest/store/store.go | 1 - loadtest/utils.go | 16 ++++------------ 3 files changed, 7 insertions(+), 17 deletions(-) diff --git a/loadtest/control/simulcontroller/scheduled_posts.go b/loadtest/control/simulcontroller/scheduled_posts.go index 4d6edb6c6..350b1cf27 100644 --- a/loadtest/control/simulcontroller/scheduled_posts.go +++ b/loadtest/control/simulcontroller/scheduled_posts.go @@ -7,10 +7,9 @@ import ( "github.com/mattermost/mattermost-load-test-ng/loadtest/user" "github.com/mattermost/mattermost/server/public/model" "math/rand" + "time" ) -const twoDaysInMilliseconds = 17_28_00_000 - func (c *SimulController) createScheduledPost(u user.User) control.UserActionResponse { if ok, resp := control.ScheduledPostsEnabled(u); resp.Err != nil { return resp @@ -51,7 +50,7 @@ func (c *SimulController) createScheduledPost(u user.User) control.UserActionRes RootId: rootId, CreateAt: model.GetMillis(), }, - ScheduledAt: loadtest.RandomFutureTime(twoDaysInMilliseconds, 10), + ScheduledAt: loadtest.RandomFutureTime(time.Hour*24*2, time.Hour*24*10), } if rand.Float64() < 0.02 { @@ -93,7 +92,7 @@ func (c *SimulController) updateScheduledPost(u user.User) control.UserActionRes } scheduledPost.Message = message - scheduledPost.ScheduledAt = loadtest.RandomFutureTime(twoDaysInMilliseconds, 10) + scheduledPost.ScheduledAt = loadtest.RandomFutureTime(time.Hour*24*2, time.Hour*24*10) if err := u.UpdateScheduledPost(channel.TeamId, scheduledPost); err != nil { return control.UserActionResponse{Err: control.NewUserError(err)} diff --git a/loadtest/store/store.go b/loadtest/store/store.go index a713a9a42..df9101252 100644 --- a/loadtest/store/store.go +++ b/loadtest/store/store.go @@ -206,7 +206,6 @@ type MutableUserStore interface { // scheduled posts SetScheduledPost(teamId string, scheduledPost *model.ScheduledPost) error - GetRandomScheduledPost() (*model.ScheduledPost, error) // posts // SetPost stores the given post. diff --git a/loadtest/utils.go b/loadtest/utils.go index e0f00cae1..61a9f21d6 100644 --- a/loadtest/utils.go +++ b/loadtest/utils.go @@ -90,18 +90,10 @@ func nextPowerOf2(val int) int { return val } -// RandomFutureTime generates a random time between (now + millisecondsFromNow) to (now + uptoDaysFromNow) in Unix milliseconds. -func RandomFutureTime(millisecondsFromNow int64, uptoDaysFromNow int) int64 { +func RandomFutureTime(deltaStart, maxUntil time.Duration) int64 { now := time.Now() - minOffset := millisecondsFromNow // Minimum offset in milliseconds - maxOffset := millisecondsFromNow + int64(uptoDaysFromNow)*86400000 // Max offset in milliseconds (1 day = 86400000 ms) - - // Generate a random offset between minOffset and maxOffset - randomOffset := minOffset + rand.Int63n(maxOffset-minOffset) - - // Add the random offset to the current time - randomFutureTime := now.Add(time.Duration(randomOffset) * time.Millisecond) - - // Return the Unix timestamp in milliseconds + diff := maxUntil - deltaStart + offset := deltaStart.Milliseconds() + rand.Int63n(diff.Milliseconds()) + randomFutureTime := now.Add(time.Duration(offset) * time.Millisecond) return randomFutureTime.UnixMilli() } From 8096d4af86986ed76a2a334337c793ce3772a65a Mon Sep 17 00:00:00 2001 From: Harshil Sharma Date: Mon, 9 Dec 2024 08:26:43 +0530 Subject: [PATCH 13/15] Cleanup --- loadtest/control/simulcontroller/controller.go | 4 ++++ loadtest/control/simulcontroller/drafts.go | 2 +- loadtest/control/simulcontroller/scheduled_posts.go | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/loadtest/control/simulcontroller/controller.go b/loadtest/control/simulcontroller/controller.go index a8eadcb56..16beb1eca 100644 --- a/loadtest/control/simulcontroller/controller.go +++ b/loadtest/control/simulcontroller/controller.go @@ -16,6 +16,10 @@ import ( "github.com/mattermost/mattermost/server/public/shared/mlog" ) +const ( + probabilityAttachFileToPost = 0.02 +) + func getActionList(c *SimulController) []userAction { actions := []userAction{ { diff --git a/loadtest/control/simulcontroller/drafts.go b/loadtest/control/simulcontroller/drafts.go index f1e3b1329..00c2a3b72 100644 --- a/loadtest/control/simulcontroller/drafts.go +++ b/loadtest/control/simulcontroller/drafts.go @@ -85,7 +85,7 @@ func (c *SimulController) upsertDraft(u user.User) control.UserActionResponse { } // 2% of the times post will have files attached. - if rand.Float64() < 0.02 { + if rand.Float64() < probabilityAttachFileToPost { if err := control.AttachFilesToDraft(u, draft); err != nil { return control.UserActionResponse{Err: control.NewUserError(err)} } diff --git a/loadtest/control/simulcontroller/scheduled_posts.go b/loadtest/control/simulcontroller/scheduled_posts.go index 350b1cf27..885ead034 100644 --- a/loadtest/control/simulcontroller/scheduled_posts.go +++ b/loadtest/control/simulcontroller/scheduled_posts.go @@ -53,7 +53,7 @@ func (c *SimulController) createScheduledPost(u user.User) control.UserActionRes ScheduledAt: loadtest.RandomFutureTime(time.Hour*24*2, time.Hour*24*10), } - if rand.Float64() < 0.02 { + if rand.Float64() < probabilityAttachFileToPost { if err := control.AttachFilesToDraft(u, &scheduledPost.Draft); err != nil { return control.UserActionResponse{Err: control.NewUserError(err)} } From 1c9a2505db7e5ab01bd5981e61fc121016683f33 Mon Sep 17 00:00:00 2001 From: Harshil Sharma Date: Thu, 19 Dec 2024 09:52:44 +0530 Subject: [PATCH 14/15] review Fixes --- .../simulcontroller/scheduled_posts.go | 12 +++---- loadtest/store/memstore/store.go | 35 +++++++++++++++---- loadtest/store/store.go | 2 +- loadtest/user/user.go | 2 +- loadtest/user/userentity/scheduled_posts.go | 15 +++----- loadtest/utils.go | 2 ++ 6 files changed, 43 insertions(+), 25 deletions(-) diff --git a/loadtest/control/simulcontroller/scheduled_posts.go b/loadtest/control/simulcontroller/scheduled_posts.go index 885ead034..c5680b0e0 100644 --- a/loadtest/control/simulcontroller/scheduled_posts.go +++ b/loadtest/control/simulcontroller/scheduled_posts.go @@ -63,7 +63,7 @@ func (c *SimulController) createScheduledPost(u user.User) control.UserActionRes return control.UserActionResponse{Err: control.NewUserError(err)} } - return control.UserActionResponse{Info: fmt.Sprintf("scheduled post created in channel id %v", channel.Id)} + return control.UserActionResponse{Info: fmt.Sprintf("scheduled post created in channel with id %s", channel.Id)} } func (c *SimulController) updateScheduledPost(u user.User) control.UserActionResponse { @@ -98,7 +98,7 @@ func (c *SimulController) updateScheduledPost(u user.User) control.UserActionRes return control.UserActionResponse{Err: control.NewUserError(err)} } - return control.UserActionResponse{Info: fmt.Sprintf("scheduled post updated in channel id %v", channel.Id)} + return control.UserActionResponse{Info: fmt.Sprintf("scheduled post updated in channel with id %s", channel.Id)} } func (c *SimulController) deleteScheduledPost(u user.User) control.UserActionResponse { @@ -116,11 +116,11 @@ func (c *SimulController) deleteScheduledPost(u user.User) control.UserActionRes return control.UserActionResponse{Info: "no scheduled posts found"} } - if err := u.DeleteScheduledPost(scheduledPost.Id); err != nil { + if err := u.DeleteScheduledPost(scheduledPost); err != nil { return control.UserActionResponse{Err: control.NewUserError(err)} } - return control.UserActionResponse{Info: fmt.Sprintf("scheduled post deleted with id %v", scheduledPost.Id)} + return control.UserActionResponse{Info: fmt.Sprintf("scheduled post with id %s deleted", scheduledPost.Id)} } func (c *SimulController) sendScheduledPostNow(u user.User) control.UserActionResponse { @@ -147,9 +147,9 @@ func (c *SimulController) sendScheduledPostNow(u user.User) control.UserActionRe return control.UserActionResponse{Err: control.NewUserError(err)} } - if err := u.DeleteScheduledPost(scheduledPost.Id); err != nil { + if err := u.DeleteScheduledPost(scheduledPost); err != nil { return control.UserActionResponse{Err: control.NewUserError(err)} } - return control.UserActionResponse{Info: fmt.Sprintf("scheduled post with id %v manually sent now", scheduledPost.Id)} + return control.UserActionResponse{Info: fmt.Sprintf("scheduled post with id %s manually sent now", scheduledPost.Id)} } diff --git a/loadtest/store/memstore/store.go b/loadtest/store/memstore/store.go index 9f7a5f9c7..459ae1086 100644 --- a/loadtest/store/memstore/store.go +++ b/loadtest/store/memstore/store.go @@ -52,7 +52,7 @@ type MemStore struct { featureFlags map[string]bool report *model.PerformanceReport channelBookmarks map[string]*model.ChannelBookmarkWithFileInfo - scheduledPosts map[string]map[string][]*model.ScheduledPost + scheduledPosts map[string]map[string][]*model.ScheduledPost // map of team ID -> channel/thread ID -> list of scheduled posts } // New returns a new instance of MemStore with the given config. @@ -1387,14 +1387,22 @@ func (s *MemStore) SetScheduledPost(teamId string, scheduledPost *model.Schedule return nil } -func (s *MemStore) DeleteScheduledPost(scheduledPostID string) { +func (s *MemStore) DeleteScheduledPost(scheduledPost *model.ScheduledPost) { s.lock.Lock() defer s.lock.Unlock() for teamId := range s.scheduledPosts { - if _, ok := s.scheduledPosts[teamId][scheduledPostID]; ok { - delete(s.scheduledPosts[teamId], scheduledPostID) - break + channelOrThreadId := scheduledPost.ChannelId + if scheduledPost.RootId != "" { + channelOrThreadId = scheduledPost.RootId + } + + // find index of scheduledPost in s.scheduledPosts[teamId][channelOrThreadId] and if found, delete it + for i, sp := range s.scheduledPosts[teamId][channelOrThreadId] { + if sp.Id == scheduledPost.Id { + s.scheduledPosts[teamId][channelOrThreadId] = append(s.scheduledPosts[teamId][channelOrThreadId][:i], s.scheduledPosts[teamId][channelOrThreadId][i+1:]...) + break + } } } } @@ -1403,9 +1411,22 @@ func (s *MemStore) UpdateScheduledPost(teamId string, scheduledPost *model.Sched s.lock.Lock() defer s.lock.Unlock() + channelOrThreadId := scheduledPost.ChannelId + if scheduledPost.RootId != "" { + channelOrThreadId = scheduledPost.RootId + } + if _, ok := s.scheduledPosts[teamId]; !ok { - s.scheduledPosts[teamId] = make(map[string][]*model.ScheduledPost) + s.scheduledPosts[teamId] = map[string][]*model.ScheduledPost{ + channelOrThreadId: {scheduledPost}, + } + return } - s.scheduledPosts[teamId][scheduledPost.Id] = append(s.scheduledPosts[teamId][scheduledPost.Id], scheduledPost) + for i := range s.scheduledPosts[teamId][channelOrThreadId] { + if s.scheduledPosts[teamId][channelOrThreadId][i].Id == scheduledPost.Id { + s.scheduledPosts[teamId][channelOrThreadId][i] = scheduledPost + break + } + } } diff --git a/loadtest/store/store.go b/loadtest/store/store.go index df9101252..a1d6697f3 100644 --- a/loadtest/store/store.go +++ b/loadtest/store/store.go @@ -167,7 +167,7 @@ type UserStore interface { DeleteChannelBookmark(bookmarkId string) error GetRandomScheduledPost() (*model.ScheduledPost, error) - DeleteScheduledPost(scheduledPostID string) + DeleteScheduledPost(scheduledPost *model.ScheduledPost) UpdateScheduledPost(teamId string, scheduledPost *model.ScheduledPost) } diff --git a/loadtest/user/user.go b/loadtest/user/user.go index 5d28354f2..01989b9f5 100644 --- a/loadtest/user/user.go +++ b/loadtest/user/user.go @@ -348,6 +348,6 @@ type User interface { // Scheduled Posts CreateScheduledPost(teamId string, scheduledPost *model.ScheduledPost) error UpdateScheduledPost(teamId string, scheduledPost *model.ScheduledPost) error - DeleteScheduledPost(scheduledPostId string) error + DeleteScheduledPost(scheduledPost *model.ScheduledPost) error GetTeamScheduledPosts(teamID string) error } diff --git a/loadtest/user/userentity/scheduled_posts.go b/loadtest/user/userentity/scheduled_posts.go index 0774208a3..d5953d134 100644 --- a/loadtest/user/userentity/scheduled_posts.go +++ b/loadtest/user/userentity/scheduled_posts.go @@ -37,23 +37,18 @@ func (ue *UserEntity) UpdateScheduledPost(teamId string, scheduledPost *model.Sc return err } - err = ue.store.SetScheduledPost(teamId, updatedScheduledPost) - if err != nil { - return err - } - ue.Store().UpdateScheduledPost(teamId, updatedScheduledPost) return nil } -func (ue *UserEntity) DeleteScheduledPost(scheduledPostId string) error { - _, _, err := ue.client.DeleteScheduledPost(context.Background(), scheduledPostId) +func (ue *UserEntity) DeleteScheduledPost(scheduledPost *model.ScheduledPost) error { + _, _, err := ue.client.DeleteScheduledPost(context.Background(), scheduledPost.Id) if err != nil { return err } - ue.Store().DeleteScheduledPost(scheduledPostId) + ue.Store().DeleteScheduledPost(scheduledPost) return nil } @@ -63,8 +58,8 @@ func (ue *UserEntity) GetTeamScheduledPosts(teamID string) error { return err } - for teamIdInResponse := range scheduledPostsByTeam { - for _, scheduledPost := range scheduledPostsByTeam[teamIdInResponse] { + for _, scheduledPostByTeamId := range scheduledPostsByTeam { + for _, scheduledPost := range scheduledPostByTeamId { err := ue.store.SetScheduledPost(teamID, scheduledPost) if err != nil { return err diff --git a/loadtest/utils.go b/loadtest/utils.go index 61a9f21d6..13cf006fd 100644 --- a/loadtest/utils.go +++ b/loadtest/utils.go @@ -90,6 +90,8 @@ func nextPowerOf2(val int) int { return val } +// RandomFutureTime returns a random Unix timestamp, in milliseconds, in the interval +// [now+deltaStart, now+maxUntil] func RandomFutureTime(deltaStart, maxUntil time.Duration) int64 { now := time.Now() diff := maxUntil - deltaStart From fe0df4b1ae1ac6e9a9a81c0c95d7a48e4531c36d Mon Sep 17 00:00:00 2001 From: Harshil Sharma Date: Mon, 23 Dec 2024 11:37:14 +0530 Subject: [PATCH 15/15] Updated RandomFutureTime --- loadtest/utils.go | 21 ++++++--- loadtest/utils_test.go | 97 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 5 deletions(-) create mode 100644 loadtest/utils_test.go diff --git a/loadtest/utils.go b/loadtest/utils.go index 13cf006fd..5304383d0 100644 --- a/loadtest/utils.go +++ b/loadtest/utils.go @@ -91,11 +91,22 @@ func nextPowerOf2(val int) int { } // RandomFutureTime returns a random Unix timestamp, in milliseconds, in the interval -// [now+deltaStart, now+maxUntil] +// [now+deltaStart, now+deltaStart+maxUntil] func RandomFutureTime(deltaStart, maxUntil time.Duration) int64 { now := time.Now() - diff := maxUntil - deltaStart - offset := deltaStart.Milliseconds() + rand.Int63n(diff.Milliseconds()) - randomFutureTime := now.Add(time.Duration(offset) * time.Millisecond) - return randomFutureTime.UnixMilli() + start := now.Add(deltaStart) + start.Add(maxUntil) + + // Generate a random duration between 0 and maxUntil + var randomDuration time.Duration + if maxUntil > 0 { + randomDuration = time.Duration(rand.Int63n(int64(maxUntil))) + } else { + randomDuration = time.Duration(0) + } + + // Add the random duration to the start time + randomTime := start.Add(randomDuration) + + return randomTime.Unix() } diff --git a/loadtest/utils_test.go b/loadtest/utils_test.go new file mode 100644 index 000000000..0d6c400d9 --- /dev/null +++ b/loadtest/utils_test.go @@ -0,0 +1,97 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +package loadtest + +import ( + "testing" + "time" +) + +func TestRandomFutureTime(t *testing.T) { + deltaStart := 10 * time.Second + maxUntil := 5 * time.Minute + + now := time.Now() + start := now.Add(deltaStart) + end := start.Add(maxUntil) + + randomTime := RandomFutureTime(deltaStart, maxUntil) + + if randomTime < start.Unix() || randomTime > end.Unix() { + t.Errorf("RandomFutureTime() = %v, want between %v and %v", randomTime, start.Unix(), end.Unix()) + } +} + +func TestRandomFutureTimeZeroDuration(t *testing.T) { + deltaStart := 0 * time.Second + maxUntil := 0 * time.Second + + now := time.Now() + expectedTime := now.Unix() + + randomTime := RandomFutureTime(deltaStart, maxUntil) + + if randomTime != expectedTime { + t.Errorf("RandomFutureTime() = %v, want %v", randomTime, expectedTime) + } +} + +func TestRandomFutureTimeNegativeDuration(t *testing.T) { + deltaStart := -10 * time.Second + maxUntil := -5 * time.Minute + + now := time.Now() + start := now.Add(deltaStart) + end := start.Add(maxUntil) + + randomTime := RandomFutureTime(deltaStart, maxUntil) + + if randomTime < end.Unix() || randomTime > start.Unix() { + t.Errorf("RandomFutureTime() = %v, want between %v and %v", randomTime, end.Unix(), start.Unix()) + } +} + +func TestRandomFutureTimeMaxUntilZero(t *testing.T) { + deltaStart := 10 * time.Second + maxUntil := 0 * time.Second + + now := time.Now() + expectedTime := now.Add(deltaStart).Unix() + + randomTime := RandomFutureTime(deltaStart, maxUntil) + + if randomTime != expectedTime { + t.Errorf("RandomFutureTime() = %v, want %v", randomTime, expectedTime) + } +} + +func TestRandomFutureTimeDeltaStartZero(t *testing.T) { + deltaStart := 0 * time.Second + maxUntil := 5 * time.Minute + + now := time.Now() + start := now + end := start.Add(maxUntil) + + randomTime := RandomFutureTime(deltaStart, maxUntil) + + if randomTime < start.Unix() || randomTime > end.Unix() { + t.Errorf("RandomFutureTime() = %v, want between %v and %v", randomTime, start.Unix(), end.Unix()) + } +} + +func TestRandomFutureTimeLargeDurations(t *testing.T) { + deltaStart := 100 * time.Hour + maxUntil := 1000 * time.Hour + + now := time.Now() + start := now.Add(deltaStart) + end := start.Add(maxUntil) + + randomTime := RandomFutureTime(deltaStart, maxUntil) + + if randomTime < start.Unix() || randomTime > end.Unix() { + t.Errorf("RandomFutureTime() = %v, want between %v and %v", randomTime, start.Unix(), end.Unix()) + } +}