From 85b1f3080c74681b6fca45625687606490408172 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 3 Sep 2024 03:05:09 +0800 Subject: [PATCH] Improve get feed with pagination (#31821) Fix #31752 @somera --------- Co-authored-by: delvh --- models/activities/action.go | 49 +++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/models/activities/action.go b/models/activities/action.go index d23f2bd986..532667d495 100644 --- a/models/activities/action.go +++ b/models/activities/action.go @@ -450,17 +450,46 @@ func GetFeeds(ctx context.Context, opts GetFeedsOptions) (ActionList, int64, err return nil, 0, err } - sess := db.GetEngine(ctx).Where(cond). - Select("`action`.*"). // this line will avoid select other joined table's columns - Join("INNER", "repository", "`repository`.id = `action`.repo_id") - - opts.SetDefaultValues() - sess = db.SetSessionPagination(sess, &opts) - actions := make([]*Action, 0, opts.PageSize) - count, err := sess.Desc("`action`.created_unix").FindAndCount(&actions) - if err != nil { - return nil, 0, fmt.Errorf("FindAndCount: %w", err) + var count int64 + + if opts.Page < 10 { // TODO: why it's 10 but other values? It's an experience value. + sess := db.GetEngine(ctx).Where(cond). + Select("`action`.*"). // this line will avoid select other joined table's columns + Join("INNER", "repository", "`repository`.id = `action`.repo_id") + + opts.SetDefaultValues() + sess = db.SetSessionPagination(sess, &opts) + + count, err = sess.Desc("`action`.created_unix").FindAndCount(&actions) + if err != nil { + return nil, 0, fmt.Errorf("FindAndCount: %w", err) + } + } else { + // First, only query which IDs are necessary, and only then query all actions to speed up the overall query + sess := db.GetEngine(ctx).Where(cond). + Select("`action`.id"). + Join("INNER", "repository", "`repository`.id = `action`.repo_id") + + opts.SetDefaultValues() + sess = db.SetSessionPagination(sess, &opts) + + actionIDs := make([]int64, 0, opts.PageSize) + if err := sess.Table("action").Desc("`action`.created_unix").Find(&actionIDs); err != nil { + return nil, 0, fmt.Errorf("Find(actionsIDs): %w", err) + } + + count, err = db.GetEngine(ctx).Where(cond). + Table("action"). + Cols("`action`.id"). + Join("INNER", "repository", "`repository`.id = `action`.repo_id").Count() + if err != nil { + return nil, 0, fmt.Errorf("Count: %w", err) + } + + if err := db.GetEngine(ctx).In("`action`.id", actionIDs).Desc("`action`.created_unix").Find(&actions); err != nil { + return nil, 0, fmt.Errorf("Find: %w", err) + } } if err := ActionList(actions).LoadAttributes(ctx); err != nil {