optimise topic list orderby
filter out forums with no topics from search queries update go version in go.mod
This commit is contained in:
parent
d86ea75cdb
commit
2330b5bfeb
|
@ -11,6 +11,11 @@ import (
|
||||||
|
|
||||||
var TopicList TopicListInt
|
var TopicList TopicListInt
|
||||||
|
|
||||||
|
const (
|
||||||
|
TopicListDefault = iota
|
||||||
|
TopicListMostViewed
|
||||||
|
)
|
||||||
|
|
||||||
type TopicListHolder struct {
|
type TopicListHolder struct {
|
||||||
List []*TopicsRow
|
List []*TopicsRow
|
||||||
ForumList []Forum
|
ForumList []Forum
|
||||||
|
@ -18,10 +23,10 @@ type TopicListHolder struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type TopicListInt interface {
|
type TopicListInt interface {
|
||||||
GetListByCanSee(canSee []int, 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 string, 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 string) (topicList []*TopicsRow, paginator Paginator, err error)
|
GetListByForum(f *Forum, page int, orderby int) (topicList []*TopicsRow, paginator Paginator, err error)
|
||||||
GetList(page int, orderby string, filterIDs []int) (topicList []*TopicsRow, forumList []Forum, paginator Paginator, err error)
|
GetList(page int, orderby int, filterIDs []int) (topicList []*TopicsRow, forumList []Forum, paginator Paginator, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type DefaultTopicList struct {
|
type DefaultTopicList struct {
|
||||||
|
@ -104,7 +109,7 @@ func (tList *DefaultTopicList) Tick() error {
|
||||||
|
|
||||||
canSeeHolders := make(map[string]*TopicListHolder)
|
canSeeHolders := make(map[string]*TopicListHolder)
|
||||||
for name, canSee := range permTree {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -130,7 +135,7 @@ func (tList *DefaultTopicList) Tick() error {
|
||||||
|
|
||||||
// TODO: Add Topics() method to *Forum?
|
// TODO: Add Topics() method to *Forum?
|
||||||
// TODO: Implement orderby
|
// 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
|
// 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)
|
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
|
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 {
|
if page == 0 {
|
||||||
page = 1
|
page = 1
|
||||||
}
|
}
|
||||||
// TODO: Cache the first three pages not just the first along with all the topics on this beaten track
|
// 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 hold *TopicListHolder
|
||||||
var ok bool
|
var ok bool
|
||||||
if group.ID%2 == 0 {
|
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)
|
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?
|
// TODO: Optimise this by filtering canSee and then fetching the forums?
|
||||||
// We need a list of the visible forums for Quick Topic
|
// We need a list of the visible forums for Quick Topic
|
||||||
// ? - Would it be useful, if we could post in social groups from /topics/?
|
// ? - 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 {
|
} else {
|
||||||
filteredForums = forumList
|
filteredForums = forumList
|
||||||
}
|
}
|
||||||
if len(filteredForums) == 1 && orderby == "" {
|
if len(filteredForums) == 1 && orderby == 0 {
|
||||||
topicList, pagi, err = tList.GetListByForum(&filteredForums[0], page, orderby)
|
topicList, pagi, err = tList.GetListByForum(&filteredForums[0], page, orderby)
|
||||||
return topicList, forumList, pagi, err
|
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
|
// 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?
|
// 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()
|
cCanSee, err := Forums.GetAllVisibleIDs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -309,7 +314,7 @@ func (tList *DefaultTopicList) GetList(page int, orderby string, filterIDs []int
|
||||||
topicCount += fcopy.TopicCount
|
topicCount += fcopy.TopicCount
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(forumList) == 1 && orderby == "" {
|
if len(forumList) == 1 && orderby == 0 {
|
||||||
topicList, pagi, err = tList.GetListByForum(&forumList[0], page, orderby)
|
topicList, pagi, err = tList.GetListByForum(&forumList[0], page, orderby)
|
||||||
return topicList, forumList, pagi, err
|
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: 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
|
// 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("argList: %+v\n",argList)
|
||||||
//log.Printf("qlist: %+v\n",qlist)
|
//log.Printf("qlist: %+v\n",qlist)
|
||||||
|
|
||||||
var orderq string
|
var orderq string
|
||||||
if orderby == "most-viewed" {
|
if orderby == TopicListMostViewed {
|
||||||
orderq = "views DESC,lastReplyAt DESC,createdBy DESC"
|
orderq = "views DESC,lastReplyAt DESC,createdBy DESC"
|
||||||
} else {
|
} else {
|
||||||
orderq = "sticky DESC,lastReplyAt DESC,createdBy DESC"
|
orderq = "sticky DESC,lastReplyAt DESC,createdBy DESC"
|
||||||
|
|
|
@ -83,7 +83,7 @@ func wsTopicListTick(h *WsHubImpl) error {
|
||||||
|
|
||||||
// Don't waste CPU time if nothing has happened
|
// Don't waste CPU time if nothing has happened
|
||||||
// TODO: Get a topic list method which strips stickies?
|
// 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 {
|
if err != nil {
|
||||||
h.lastTick = tickStart
|
h.lastTick = tickStart
|
||||||
return err // TODO: Do we get ErrNoRows here?
|
return err // TODO: Do we get ErrNoRows here?
|
||||||
|
@ -152,7 +152,7 @@ func wsTopicListTick(h *WsHubImpl) error {
|
||||||
|
|
||||||
canSeeRenders := make(map[string][]byte)
|
canSeeRenders := make(map[string][]byte)
|
||||||
for name, canSee := range canSeeMap {
|
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 {
|
if err != nil {
|
||||||
return err // TODO: Do we get ErrNoRows here?
|
return err // TODO: Do we get ErrNoRows here?
|
||||||
}
|
}
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -24,3 +24,5 @@ require (
|
||||||
gopkg.in/sourcemap.v1 v1.0.5 // indirect
|
gopkg.in/sourcemap.v1 v1.0.5 // indirect
|
||||||
gopkg.in/src-d/go-git.v4 v4.7.1
|
gopkg.in/src-d/go-git.v4 v4.7.1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
go 1.13
|
||||||
|
|
6
main.go
6
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...
|
// 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
ctList := make([]*c.TopicsRow, len(tList))
|
ctList := make([]*c.TopicsRow, len(tList))
|
||||||
copy(ctList, 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ func afterDBInit() (err error) {
|
||||||
ctList = append(ctList, tItem)
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ func ViewForum(w http.ResponseWriter, r *http.Request, user c.User, header *c.He
|
||||||
header.Title = forum.Name
|
header.Title = forum.Name
|
||||||
header.OGDesc = forum.Desc
|
header.OGDesc = forum.Desc
|
||||||
|
|
||||||
topicList, pagi, err := c.TopicList.GetListByForum(forum, page, "")
|
topicList, pagi, err := c.TopicList.GetListByForum(forum, page, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
return c.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,15 +24,15 @@ func TopicList(w http.ResponseWriter, r *http.Request, user c.User, h *c.Header)
|
||||||
if skip || rerr != nil {
|
if skip || rerr != nil {
|
||||||
return rerr
|
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 {
|
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
|
// 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.Title = phrases.GetTitlePhrase("topics")
|
||||||
h.Zone = "topics"
|
h.Zone = "topics"
|
||||||
h.Path = "/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
|
// TODO: Simplify this block after initially landing search
|
||||||
var topicList []*c.TopicsRow
|
var topicList []*c.TopicsRow
|
||||||
var forumList []c.Forum
|
var forumList []c.Forum
|
||||||
var paginator c.Paginator
|
var pagi c.Paginator
|
||||||
q := r.FormValue("q")
|
q := r.FormValue("q")
|
||||||
if q != "" && c.RepliesSearch != nil {
|
if q != "" && c.RepliesSearch != nil {
|
||||||
var canSee []int
|
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 {
|
for _, fid := range fids {
|
||||||
if inSlice(canSee, fid) {
|
if inSlice(canSee, fid) {
|
||||||
f := c.Forums.DirtyGet(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?
|
// TODO: Add a hook here for plugin_guilds?
|
||||||
cfids = append(cfids, fid)
|
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?
|
// TODO: De-dupe this logic in common/topic_list.go?
|
||||||
for _, t := range topicList {
|
for _, t := range topicList {
|
||||||
t.Link = c.BuildTopicURL(c.NameToSlug(t.Title), t.ID)
|
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)
|
forum := c.Forums.DirtyGet(t.ParentID)
|
||||||
t.ForumName = forum.Name
|
t.ForumName = forum.Name
|
||||||
t.ForumLink = forum.Link
|
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
|
// TODO: Reduce the amount of boilerplate here
|
||||||
if r.FormValue("js") == "1" {
|
if r.FormValue("js") == "1" {
|
||||||
outBytes, err := wsTopicList(topicList, paginator.LastPage).MarshalJSON()
|
outBytes, err := wsTopicList(topicList, pagi.LastPage).MarshalJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
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")
|
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)
|
return renderTemplate("topics", w, r, h, pi)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Pass a struct back rather than passing back so many variables
|
// TODO: Pass a struct back rather than passing back so many variables
|
||||||
if user.IsSuperAdmin {
|
if user.IsSuperAdmin {
|
||||||
topicList, forumList, paginator, err = c.TopicList.GetList(page, tsorder, fids)
|
topicList, forumList, pagi, err = c.TopicList.GetList(page, tsorder, fids)
|
||||||
} else {
|
} 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 {
|
if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
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
|
// TODO: Reduce the amount of boilerplate here
|
||||||
if r.FormValue("js") == "1" {
|
if r.FormValue("js") == "1" {
|
||||||
outBytes, err := wsTopicList(topicList, paginator.LastPage).MarshalJSON()
|
outBytes, err := wsTopicList(topicList, pagi.LastPage).MarshalJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
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
|
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)
|
return renderTemplate("topics", w, r, h, pi)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue