From 279754c6b05f73abbd397e1da502812e487a7061 Mon Sep 17 00:00:00 2001 From: Jesse Hallam Date: Fri, 4 Nov 2022 12:05:59 -0300 Subject: [PATCH] Refactor common JoinThread helper struct (#21511) * Refactor common JoinThread helper struct * avoid exporting ToThreadResponse --- store/sqlstore/thread_store.go | 117 ++++++++++++--------------------- 1 file changed, 43 insertions(+), 74 deletions(-) diff --git a/store/sqlstore/thread_store.go b/store/sqlstore/thread_store.go index 7cb84099a3..2e94d1eb3c 100644 --- a/store/sqlstore/thread_store.go +++ b/store/sqlstore/thread_store.go @@ -18,6 +18,42 @@ import ( "github.com/mattermost/mattermost-server/v6/utils" ) +// JoinedThread allows querying the Threads + Posts table in a single query, before looking up +// users and unpacking into a model.ThreadResponse. +type JoinedThread struct { + PostId string + ReplyCount int64 + LastReplyAt int64 + LastViewedAt int64 + UnreadReplies int64 + UnreadMentions int64 + Participants model.StringArray + ThreadDeleteAt int64 + TeamId string + model.Post +} + +func (thread *JoinedThread) toThreadResponse(users map[string]*model.User) *model.ThreadResponse { + threadParticipants := make([]*model.User, 0, len(thread.Participants)) + for _, participantUserId := range thread.Participants { + if participant, ok := users[participantUserId]; ok { + threadParticipants = append(threadParticipants, participant) + } + } + + return &model.ThreadResponse{ + PostId: thread.PostId, + ReplyCount: thread.ReplyCount, + LastReplyAt: thread.LastReplyAt, + LastViewedAt: thread.LastViewedAt, + UnreadReplies: thread.UnreadReplies, + UnreadMentions: thread.UnreadMentions, + Participants: threadParticipants, + Post: thread.Post.ToNilIfInvalid(), + DeleteAt: thread.ThreadDeleteAt, + } +} + type SqlThreadStore struct { *SqlStore @@ -183,19 +219,6 @@ func (s *SqlThreadStore) GetThreadsForUser(userId, teamId string, opts model.Get pageSize = opts.PageSize } - var threads []*struct { - PostId string - ReplyCount int64 - LastReplyAt int64 - LastViewedAt int64 - UnreadReplies int64 - UnreadMentions int64 - Participants model.StringArray - ThreadDeleteAt int64 - TeamId string - model.Post - } - unreadRepliesQuery := sq. Select("COUNT(Posts.Id)"). From("Posts"). @@ -258,6 +281,7 @@ func (s *SqlThreadStore) GetThreadsForUser(userId, teamId string, opts model.Get OrderBy("Threads.LastReplyAt " + order). Limit(pageSize) + var threads []*JoinedThread err := s.GetReplicaX().SelectBuilder(&threads, query) if err != nil { return nil, errors.Wrapf(err, "failed to fetch threads for user id=%s", userId) @@ -290,27 +314,7 @@ func (s *SqlThreadStore) GetThreadsForUser(userId, teamId string, opts model.Get result := make([]*model.ThreadResponse, 0, len(threads)) for _, thread := range threads { - // Find only this thread's participants - threadParticipants := make([]*model.User, 0, len(thread.Participants)) - for _, participantUserId := range thread.Participants { - participant, ok := allParticipants[participantUserId] - if !ok { - return nil, errors.Errorf("cannot find participant with user id=%s for thread id=%s", participantUserId, thread.PostId) - } - threadParticipants = append(threadParticipants, participant) - } - - result = append(result, &model.ThreadResponse{ - PostId: thread.PostId, - ReplyCount: thread.ReplyCount, - LastReplyAt: thread.LastReplyAt, - LastViewedAt: thread.LastViewedAt, - UnreadReplies: thread.UnreadReplies, - UnreadMentions: thread.UnreadMentions, - Participants: threadParticipants, - Post: thread.Post.ToNilIfInvalid(), - DeleteAt: thread.ThreadDeleteAt, - }) + result = append(result, thread.toThreadResponse(allParticipants)) } return result, nil @@ -437,20 +441,6 @@ func (s *SqlThreadStore) GetThreadForUser(teamId string, threadMembership *model return nil, nil // in case the thread is not followed anymore - return nil error to be interpreted as 404 } - type JoinedThread struct { - PostId string - Following bool - ReplyCount int64 - LastReplyAt int64 - LastViewedAt int64 - UnreadReplies int64 - UnreadMentions int64 - Participants model.StringArray - ThreadDeleteAt int64 - TeamId string - model.Post - } - unreadRepliesQuery := sq. Select("COUNT(Posts.Id)"). From("Posts"). @@ -501,33 +491,12 @@ func (s *SqlThreadStore) GetThreadForUser(teamId string, threadMembership *model } } - participants := []*model.User{} - for _, participantId := range thread.Participants { - var participant *model.User - for _, u := range users { - if u.Id == participantId { - participant = u - break - } - } - if participant != nil { - participants = append(participants, participant) - } + usersMap := make(map[string]*model.User) + for _, user := range users { + usersMap[user.Id] = user } - result := &model.ThreadResponse{ - PostId: thread.PostId, - ReplyCount: thread.ReplyCount, - LastReplyAt: thread.LastReplyAt, - LastViewedAt: thread.LastViewedAt, - UnreadReplies: thread.UnreadReplies, - UnreadMentions: thread.UnreadMentions, - Participants: participants, - Post: thread.Post.ToNilIfInvalid(), - DeleteAt: thread.ThreadDeleteAt, - } - - return result, nil + return thread.toThreadResponse(usersMap), nil } // MarkAllAsReadByChannels marks thread membership for the given users in the given channels @@ -1012,7 +981,7 @@ func (s *SqlThreadStore) GetTopThreadsForUserSince(teamID string, userID string, var args []any // gets all threads within the team which user follows. - query := `select + query := `select threads_list.PostId, threads_list.ReplyCount, threads_list.ChannelId,