From 2330b5bfeb3840f11022a5f22f2132b7a19c40f6 Mon Sep 17 00:00:00 2001 From: Azareal Date: Tue, 3 Mar 2020 14:25:18 +1000 Subject: [PATCH] optimise topic list orderby filter out forums with no topics from search queries update go version in go.mod --- common/topic_list.go | 33 +++++++++++++++++++-------------- common/ws_hub.go | 4 ++-- go.mod | 2 ++ main.go | 6 +++--- routes/forum.go | 2 +- routes/topic_list.go | 24 ++++++++++++------------ 6 files changed, 39 insertions(+), 32 deletions(-) diff --git a/common/topic_list.go b/common/topic_list.go index 8c0208cd..44791cb2 100644 --- a/common/topic_list.go +++ b/common/topic_list.go @@ -11,6 +11,11 @@ import ( var TopicList TopicListInt +const ( + TopicListDefault = iota + TopicListMostViewed +) + type TopicListHolder struct { List []*TopicsRow ForumList []Forum @@ -18,10 +23,10 @@ type TopicListHolder struct { } type TopicListInt interface { - GetListByCanSee(canSee []int, page int, orderby string, filterIDs []int) (topicList []*TopicsRow, forumList []Forum, paginator Paginator, err error) - GetListByGroup(group *Group, page int, orderby string, filterIDs []int) (topicList []*TopicsRow, forumList []Forum, paginator Paginator, err error) - GetListByForum(f *Forum, page int, orderby string) (topicList []*TopicsRow, paginator Paginator, err error) - GetList(page int, orderby string, filterIDs []int) (topicList []*TopicsRow, forumList []Forum, paginator Paginator, err error) + GetListByCanSee(canSee []int, page int, orderby int, filterIDs []int) (topicList []*TopicsRow, forumList []Forum, paginator Paginator, err error) + GetListByGroup(group *Group, page int, orderby int, filterIDs []int) (topicList []*TopicsRow, forumList []Forum, paginator Paginator, err error) + GetListByForum(f *Forum, page int, orderby int) (topicList []*TopicsRow, paginator Paginator, err error) + GetList(page int, orderby int, filterIDs []int) (topicList []*TopicsRow, forumList []Forum, paginator Paginator, err error) } type DefaultTopicList struct { @@ -104,7 +109,7 @@ func (tList *DefaultTopicList) Tick() error { canSeeHolders := make(map[string]*TopicListHolder) for name, canSee := range permTree { - topicList, forumList, paginator, err := tList.GetListByCanSee(canSee, 1, "", nil) + topicList, forumList, paginator, err := tList.GetListByCanSee(canSee, 1, 0, nil) if err != nil { return err } @@ -130,7 +135,7 @@ func (tList *DefaultTopicList) Tick() error { // TODO: Add Topics() method to *Forum? // TODO: Implement orderby -func (tList *DefaultTopicList) GetListByForum(f *Forum, page int, orderby string) (topicList []*TopicsRow, paginator Paginator, err error) { +func (tList *DefaultTopicList) GetListByForum(f *Forum, page int, orderby int) (topicList []*TopicsRow, paginator Paginator, err error) { // TODO: Does forum.TopicCount take the deleted items into consideration for guests? We don't have soft-delete yet, only hard-delete offset, page, lastPage := PageOffset(f.TopicCount, page, Config.ItemsPerPage) @@ -189,12 +194,12 @@ func (tList *DefaultTopicList) GetListByForum(f *Forum, page int, orderby string return topicList, Paginator{pageList, page, lastPage}, nil } -func (tList *DefaultTopicList) GetListByGroup(group *Group, page int, orderby string, filterIDs []int) (topicList []*TopicsRow, forumList []Forum, paginator Paginator, err error) { +func (tList *DefaultTopicList) GetListByGroup(group *Group, page int, orderby int, filterIDs []int) (topicList []*TopicsRow, forumList []Forum, paginator Paginator, err error) { if page == 0 { page = 1 } // TODO: Cache the first three pages not just the first along with all the topics on this beaten track - if page == 1 && orderby == "" && len(filterIDs) == 0 { + if page == 1 && orderby == 0 && len(filterIDs) == 0 { var hold *TopicListHolder var ok bool if group.ID%2 == 0 { @@ -216,7 +221,7 @@ func (tList *DefaultTopicList) GetListByGroup(group *Group, page int, orderby st return tList.GetListByCanSee(group.CanSee, page, orderby, filterIDs) } -func (tList *DefaultTopicList) GetListByCanSee(canSee []int, page int, orderby string, filterIDs []int) (topicList []*TopicsRow, forumList []Forum, pagi Paginator, err error) { +func (tList *DefaultTopicList) GetListByCanSee(canSee []int, page int, orderby int, filterIDs []int) (topicList []*TopicsRow, forumList []Forum, pagi Paginator, err error) { // TODO: Optimise this by filtering canSee and then fetching the forums? // We need a list of the visible forums for Quick Topic // ? - Would it be useful, if we could post in social groups from /topics/? @@ -248,7 +253,7 @@ func (tList *DefaultTopicList) GetListByCanSee(canSee []int, page int, orderby s } else { filteredForums = forumList } - if len(filteredForums) == 1 && orderby == "" { + if len(filteredForums) == 1 && orderby == 0 { topicList, pagi, err = tList.GetListByForum(&filteredForums[0], page, orderby) return topicList, forumList, pagi, err } @@ -270,7 +275,7 @@ func (tList *DefaultTopicList) GetListByCanSee(canSee []int, page int, orderby s } // TODO: Reduce the number of returns -func (tList *DefaultTopicList) GetList(page int, orderby string, filterIDs []int) (topicList []*TopicsRow, forumList []Forum, pagi Paginator, err error) { +func (tList *DefaultTopicList) GetList(page, orderby int, filterIDs []int) (topicList []*TopicsRow, forumList []Forum, pagi Paginator, err error) { // TODO: Make CanSee a method on *Group with a canSee field? Have a CanSee method on *User to cover the case of superadmins? cCanSee, err := Forums.GetAllVisibleIDs() if err != nil { @@ -309,7 +314,7 @@ func (tList *DefaultTopicList) GetList(page int, orderby string, filterIDs []int topicCount += fcopy.TopicCount } } - if len(forumList) == 1 && orderby == "" { + if len(forumList) == 1 && orderby == 0 { topicList, pagi, err = tList.GetListByForum(&forumList[0], page, orderby) return topicList, forumList, pagi, err } @@ -327,12 +332,12 @@ func (tList *DefaultTopicList) GetList(page int, orderby string, filterIDs []int // TODO: Rename this to TopicListStore and pass back a TopicList instance holding the pagination data and topic list rather than passing them back one argument at a time // TODO: Make orderby an enum of sorts -func (tList *DefaultTopicList) getList(page int, orderby string, topicCount int, argList []interface{}, qlist string) (topicList []*TopicsRow, paginator Paginator, err error) { +func (tList *DefaultTopicList) getList(page, orderby, topicCount int, argList []interface{}, qlist string) (topicList []*TopicsRow, paginator Paginator, err error) { //log.Printf("argList: %+v\n",argList) //log.Printf("qlist: %+v\n",qlist) var orderq string - if orderby == "most-viewed" { + if orderby == TopicListMostViewed { orderq = "views DESC,lastReplyAt DESC,createdBy DESC" } else { orderq = "sticky DESC,lastReplyAt DESC,createdBy DESC" diff --git a/common/ws_hub.go b/common/ws_hub.go index 588ab3dd..0e084309 100644 --- a/common/ws_hub.go +++ b/common/ws_hub.go @@ -83,7 +83,7 @@ func wsTopicListTick(h *WsHubImpl) error { // Don't waste CPU time if nothing has happened // TODO: Get a topic list method which strips stickies? - tList, _, _, err := TopicList.GetList(1, "", nil) + tList, _, _, err := TopicList.GetList(1, 0, nil) if err != nil { h.lastTick = tickStart return err // TODO: Do we get ErrNoRows here? @@ -152,7 +152,7 @@ func wsTopicListTick(h *WsHubImpl) error { canSeeRenders := make(map[string][]byte) for name, canSee := range canSeeMap { - topicList, forumList, _, err := TopicList.GetListByCanSee(canSee, 1, "", nil) + topicList, forumList, _, err := TopicList.GetListByCanSee(canSee, 1, 0, nil) if err != nil { return err // TODO: Do we get ErrNoRows here? } diff --git a/go.mod b/go.mod index c0cf972b..ef6803b7 100644 --- a/go.mod +++ b/go.mod @@ -24,3 +24,5 @@ require ( gopkg.in/sourcemap.v1 v1.0.5 // indirect gopkg.in/src-d/go-git.v4 v4.7.1 ) + +go 1.13 diff --git a/main.go b/main.go index d468dc7d..162793b2 100644 --- a/main.go +++ b/main.go @@ -74,14 +74,14 @@ func afterDBInit() (err error) { } // TODO: Use the same cached data for both the topic list and the topic fetches... - tList, _, _, err := c.TopicList.GetListByCanSee(group.CanSee, 1, "", nil) + tList, _, _, err := c.TopicList.GetListByCanSee(group.CanSee, 1, 0, nil) if err != nil { return err } ctList := make([]*c.TopicsRow, len(tList)) copy(ctList, tList) - tList, _, _, err = c.TopicList.GetListByCanSee(group.CanSee, 2, "", nil) + tList, _, _, err = c.TopicList.GetListByCanSee(group.CanSee, 2, 0, nil) if err != nil { return err } @@ -89,7 +89,7 @@ func afterDBInit() (err error) { ctList = append(ctList, tItem) } - tList, _, _, err = c.TopicList.GetListByCanSee(group.CanSee, 3, "", nil) + tList, _, _, err = c.TopicList.GetListByCanSee(group.CanSee, 3, 0, nil) if err != nil { return err } diff --git a/routes/forum.go b/routes/forum.go index d868c114..062f48d7 100644 --- a/routes/forum.go +++ b/routes/forum.go @@ -37,7 +37,7 @@ func ViewForum(w http.ResponseWriter, r *http.Request, user c.User, header *c.He header.Title = forum.Name header.OGDesc = forum.Desc - topicList, pagi, err := c.TopicList.GetListByForum(forum, page, "") + topicList, pagi, err := c.TopicList.GetListByForum(forum, page, 0) if err != nil { return c.InternalError(err, w, r) } diff --git a/routes/topic_list.go b/routes/topic_list.go index a3929e33..e5a4005a 100644 --- a/routes/topic_list.go +++ b/routes/topic_list.go @@ -24,15 +24,15 @@ func TopicList(w http.ResponseWriter, r *http.Request, user c.User, h *c.Header) if skip || rerr != nil { return rerr } - return TopicListCommon(w, r, user, h, "lastupdated", "") + return TopicListCommon(w, r, user, h, "lastupdated", 0) } func TopicListMostViewed(w http.ResponseWriter, r *http.Request, user c.User, h *c.Header) c.RouteError { - return TopicListCommon(w, r, user, h, "mostviewed", "most-viewed") + return TopicListCommon(w, r, user, h, "mostviewed", c.TopicListMostViewed) } // TODO: Implement search -func TopicListCommon(w http.ResponseWriter, r *http.Request, user c.User, h *c.Header, torder, tsorder string) c.RouteError { +func TopicListCommon(w http.ResponseWriter, r *http.Request, user c.User, h *c.Header, torder string, tsorder int) c.RouteError { h.Title = phrases.GetTitlePhrase("topics") h.Zone = "topics" h.Path = "/topics/" @@ -70,7 +70,7 @@ func TopicListCommon(w http.ResponseWriter, r *http.Request, user c.User, h *c.H // TODO: Simplify this block after initially landing search var topicList []*c.TopicsRow var forumList []c.Forum - var paginator c.Paginator + var pagi c.Paginator q := r.FormValue("q") if q != "" && c.RepliesSearch != nil { var canSee []int @@ -96,7 +96,7 @@ func TopicListCommon(w http.ResponseWriter, r *http.Request, user c.User, h *c.H for _, fid := range fids { if inSlice(canSee, fid) { f := c.Forums.DirtyGet(fid) - if f.Name != "" && f.Active && (f.ParentType == "" || f.ParentType == "forum") { + if f.Name != "" && f.Active && (f.ParentType == "" || f.ParentType == "forum") && f.TopicCount != 0 { // TODO: Add a hook here for plugin_guilds? cfids = append(cfids, fid) } @@ -143,7 +143,7 @@ func TopicListCommon(w http.ResponseWriter, r *http.Request, user c.User, h *c.H // TODO: De-dupe this logic in common/topic_list.go? for _, t := range topicList { t.Link = c.BuildTopicURL(c.NameToSlug(t.Title), t.ID) - // TODO: Pass forum to something like topic.Forum and use that instead of these two properties? Could be more flexible. + // TODO: Pass forum to something like t.Forum and use that instead of these two properties? Could be more flexible. forum := c.Forums.DirtyGet(t.ParentID) t.ForumName = forum.Name t.ForumLink = forum.Link @@ -157,7 +157,7 @@ func TopicListCommon(w http.ResponseWriter, r *http.Request, user c.User, h *c.H // TODO: Reduce the amount of boilerplate here if r.FormValue("js") == "1" { - outBytes, err := wsTopicList(topicList, paginator.LastPage).MarshalJSON() + outBytes, err := wsTopicList(topicList, pagi.LastPage).MarshalJSON() if err != nil { return c.InternalError(err, w, r) } @@ -166,15 +166,15 @@ func TopicListCommon(w http.ResponseWriter, r *http.Request, user c.User, h *c.H } h.Title = phrases.GetTitlePhrase("topics_search") - pi := c.TopicListPage{h, topicList, forumList, c.Config.DefaultForum, c.TopicListSort{torder, false}, paginator} + pi := c.TopicListPage{h, topicList, forumList, c.Config.DefaultForum, c.TopicListSort{torder, false}, pagi} return renderTemplate("topics", w, r, h, pi) } // TODO: Pass a struct back rather than passing back so many variables if user.IsSuperAdmin { - topicList, forumList, paginator, err = c.TopicList.GetList(page, tsorder, fids) + topicList, forumList, pagi, err = c.TopicList.GetList(page, tsorder, fids) } else { - topicList, forumList, paginator, err = c.TopicList.GetListByGroup(group, page, tsorder, fids) + topicList, forumList, pagi, err = c.TopicList.GetListByGroup(group, page, tsorder, fids) } if err != nil { return c.InternalError(err, w, r) @@ -182,7 +182,7 @@ func TopicListCommon(w http.ResponseWriter, r *http.Request, user c.User, h *c.H // TODO: Reduce the amount of boilerplate here if r.FormValue("js") == "1" { - outBytes, err := wsTopicList(topicList, paginator.LastPage).MarshalJSON() + outBytes, err := wsTopicList(topicList, pagi.LastPage).MarshalJSON() if err != nil { return c.InternalError(err, w, r) } @@ -190,6 +190,6 @@ func TopicListCommon(w http.ResponseWriter, r *http.Request, user c.User, h *c.H return nil } - pi := c.TopicListPage{h, topicList, forumList, c.Config.DefaultForum, c.TopicListSort{torder, false}, paginator} + pi := c.TopicListPage{h, topicList, forumList, c.Config.DefaultForum, c.TopicListSort{torder, false}, pagi} return renderTemplate("topics", w, r, h, pi) }