-
Notifications
You must be signed in to change notification settings - Fork 43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Scheduled post #848
base: master
Are you sure you want to change the base?
Scheduled post #848
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like some debug fmt.Println
statements are still left over from debugging. Let's clean them up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you so much for all your work on this, great job! I left some comments below, and I also agree with Agniva: we should remove all the fmt.Println
lines.
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)} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably move this 0.02 ratio to a global constant, we're using it in many places now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only in 5 places all over excluding tests. I don't think a constant for 2% makes sense. Its doesn't have any special meaning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, I didn't mean the number 0.02
specifically, but a constant for when to attach files to a post, for which we use 2%. We use that exact meaning elsewhere (probably less than 5 places, but more than 1, I'd say)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
loadtest/store/memstore/store.go
Outdated
@@ -52,6 +52,7 @@ type MemStore struct { | |||
featureFlags map[string]bool | |||
report *model.PerformanceReport | |||
channelBookmarks map[string]*model.ChannelBookmarkWithFileInfo | |||
scheduledPosts map[string]map[string]*model.ScheduledPost |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, please update the (s *MemStore) Clear()
method to clear this field as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
loadtest/store/memstore/random.go
Outdated
return selectedPost, nil | ||
} | ||
|
||
func (s *MemStore) DeleteScheduledPost(scheduledPostID string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The delete and update methods should not be in random.go. Let's move this to memstore/store.go.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@agnivade @agarciamontoro can you please re-review this? I've made the fixes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will leave the store logic to Alejandro.
loadtest/store/store.go
Outdated
@@ -200,6 +204,10 @@ type MutableUserStore interface { | |||
// SetDrafts stores the given drafts. | |||
SetDrafts(teamId string, drafts []*model.Draft) error | |||
|
|||
// scheduled posts | |||
SetScheduledPost(teamId string, scheduledPost *model.ScheduledPost) error | |||
GetRandomScheduledPost() (*model.ScheduledPost, error) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MutableUserStore
embeds UserStore
. So there is no need to repeat GetRandomScheduledPost
here. UserStore
should have GetRandomScheduledPost
. And MutableUserStore should have the Set/Update/Delete methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
for teamIdInResponse := range scheduledPostsByTeam { | ||
for _, scheduledPost := range scheduledPostsByTeam[teamIdInResponse] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can just do for _, v := range scheduledPostsByTeam {
instead of 2 loops.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd still need two loops. scheduledPostsByTeam is a map[string][]*model.ScheduledPosts
, and I need to iterate the individual scheduled posts from that array. I could use for _, v := range scheduledPostsByTeam
but then I'd need another loop to iterate items from v
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah right. Indeed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer using the value from range
as well, that way you don't need to access it later. Quite a nit, but I had to stop and try to understand why we weren't doing that, so I guess it's better to just stick to the convention.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, @harshilsharma63, and sorry for the delay in the review! Some more comments below.
err = ue.store.SetScheduledPost(teamId, updatedScheduledPost) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
ue.Store().UpdateScheduledPost(teamId, updatedScheduledPost) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to set it and then update it? Also, we should check the error from UpdateScheduledPost
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just update should be fine, fixed this.
loadtest/store/memstore/store.go
Outdated
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 | ||
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we error if the post doesn't exist?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't really matter.
ue.Store().DeleteScheduledPost(scheduledPostId) | ||
return nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now DeleteScheduledPost doesn't return an error, but maybe it should (I left a comment for that). If we decide that's a good decision, then we need to return its error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think its of any use returning error from delete method, it doesn't matter
for teamIdInResponse := range scheduledPostsByTeam { | ||
for _, scheduledPost := range scheduledPostsByTeam[teamIdInResponse] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer using the value from range
as well, that way you don't need to access it later. Quite a nit, but I had to stop and try to understand why we weren't doing that, so I guess it's better to just stick to the convention.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, @harshilsharma63! I've left a comment in the RandomFutureTime
function, and I have an additional ask: I do think we should error out in MemStore
's DeleteScheduledPost
and UpdateScheduledPost
if the post is not found, and log an error if that's the case. It shouldn't happen and may point to other problems in the load-test.
loadtest/utils.go
Outdated
// RandomFutureTime returns a random Unix timestamp, in milliseconds, in the interval | ||
// [now+deltaStart, now+maxUntil] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment is actually correct, thanks! But it surfaced a bug in this function: if maxUntil
is smaller than deltaStart
(let's say, you call RandomFutureTime(10*time.Second, 9*time.Second)
, then rand.Int63n
panics because it gets a negative number). We should fix the function so that the interval is actually [now+deltaStart, now+deltaStart+maxUntil]
, and add unit testing for this function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
Both Alejandro and Claudio are out. I will take another quick look and ask for a stamp approval. |
I gave it a test run and found some minor issues. We should be good to go after that. 1. Incorrect error/info logging when there are no scheduled posts. Log line is:
Note that the log level is error, but it's just a case of scheduled posts not being available. And we are correctly doing it here: 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"}
} But the issue is that The right way is to return an error variable and check for it. See for example if len(teams) == 0 {
return model.Team{}, ErrTeamStoreEmpty
} and then we check for the error at call site: team, err := u.Store().RandomTeam(store.SelectMemberOf | store.SelectNotCurrent)
if errors.Is(err, memstore.ErrTeamStoreEmpty) {
return control.UserActionResponse{Info: "no other team to switch to"}
} else if err != nil {
return control.UserActionResponse{Err: control.NewUserError(err)}
} We should apply the same logic while calling 2. Invalid scheduled at time:
This is what I see in the server logs:
If we fix the above 2 issues, we should be good to go. |
Summary
Adding scheduled posts support to load test tool.
Ticket Link
Fixes https://mattermost.atlassian.net/browse/MM-61486