aboutsummaryrefslogtreecommitdiffstats
path: root/modules/indexer/issues
diff options
context:
space:
mode:
authorJason Song <i@wolfogre.com>2023-08-23 10:29:17 +0800
committerGitHub <noreply@github.com>2023-08-23 02:29:17 +0000
commit5db21ce7e10ba78ede8841bea9db7a63adbececb (patch)
tree0e73df14b63b18becf7af115706105ad0be6a6f8 /modules/indexer/issues
parent3b91b2d6b12b9c9c18406f484775925bbd557618 (diff)
downloadgitea-5db21ce7e10ba78ede8841bea9db7a63adbececb.tar.gz
gitea-5db21ce7e10ba78ede8841bea9db7a63adbececb.zip
Fix counting and filtering on the dashboard page for issues (#26657)
This PR has multiple parts, and I didn't split them because it's not easy to test them separately since they are all about the dashboard page for issues. 1. Support counting issues via indexer to fix #26361 2. Fix repo selection so it also fixes #26653 3. Keep keywords in filter links. The first two are regressions of #26012. After: https://github.com/go-gitea/gitea/assets/9418365/71dfea7e-d9e2-42b6-851a-cc081435c946 Thanks to @CaiCandong for helping with some tests.
Diffstat (limited to 'modules/indexer/issues')
-rw-r--r--modules/indexer/issues/indexer.go41
-rw-r--r--modules/indexer/issues/internal/model.go13
2 files changed, 51 insertions, 3 deletions
diff --git a/modules/indexer/issues/indexer.go b/modules/indexer/issues/indexer.go
index 6619949104..020659c82b 100644
--- a/modules/indexer/issues/indexer.go
+++ b/modules/indexer/issues/indexer.go
@@ -13,6 +13,7 @@ import (
db_model "code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/indexer/issues/bleve"
"code.gitea.io/gitea/modules/indexer/issues/db"
@@ -277,7 +278,7 @@ func IsAvailable(ctx context.Context) bool {
}
// SearchOptions indicates the options for searching issues
-type SearchOptions internal.SearchOptions
+type SearchOptions = internal.SearchOptions
const (
SortByCreatedDesc = internal.SortByCreatedDesc
@@ -291,7 +292,6 @@ const (
)
// SearchIssues search issues by options.
-// It returns issue ids and a bool value indicates if the result is imprecise.
func SearchIssues(ctx context.Context, opts *SearchOptions) ([]int64, int64, error) {
indexer := *globalIndexer.Load()
@@ -305,7 +305,7 @@ func SearchIssues(ctx context.Context, opts *SearchOptions) ([]int64, int64, err
indexer = db.NewIndexer()
}
- result, err := indexer.Search(ctx, (*internal.SearchOptions)(opts))
+ result, err := indexer.Search(ctx, opts)
if err != nil {
return nil, 0, err
}
@@ -317,3 +317,38 @@ func SearchIssues(ctx context.Context, opts *SearchOptions) ([]int64, int64, err
return ret, result.Total, nil
}
+
+// CountIssues counts issues by options. It is a shortcut of SearchIssues(ctx, opts) but only returns the total count.
+func CountIssues(ctx context.Context, opts *SearchOptions) (int64, error) {
+ opts = opts.Copy(func(options *SearchOptions) { opts.Paginator = &db_model.ListOptions{PageSize: 0} })
+
+ _, total, err := SearchIssues(ctx, opts)
+ return total, err
+}
+
+// CountIssuesByRepo counts issues by options and group by repo id.
+// It's not a complete implementation, since it requires the caller should provide the repo ids.
+// That means opts.RepoIDs must be specified, and opts.AllPublic must be false.
+// It's good enough for the current usage, and it can be improved if needed.
+// TODO: use "group by" of the indexer engines to implement it.
+func CountIssuesByRepo(ctx context.Context, opts *SearchOptions) (map[int64]int64, error) {
+ if len(opts.RepoIDs) == 0 {
+ return nil, fmt.Errorf("opts.RepoIDs must be specified")
+ }
+ if opts.AllPublic {
+ return nil, fmt.Errorf("opts.AllPublic must be false")
+ }
+
+ repoIDs := container.SetOf(opts.RepoIDs...).Values()
+ ret := make(map[int64]int64, len(repoIDs))
+ // TODO: it could be faster if do it in parallel for some indexer engines. Improve it if users report it's slow.
+ for _, repoID := range repoIDs {
+ count, err := CountIssues(ctx, opts.Copy(func(o *internal.SearchOptions) { o.RepoIDs = []int64{repoID} }))
+ if err != nil {
+ return nil, err
+ }
+ ret[repoID] = count
+ }
+
+ return ret, nil
+}
diff --git a/modules/indexer/issues/internal/model.go b/modules/indexer/issues/internal/model.go
index 2de1e0e2bf..031745dd2f 100644
--- a/modules/indexer/issues/internal/model.go
+++ b/modules/indexer/issues/internal/model.go
@@ -109,6 +109,19 @@ type SearchOptions struct {
SortBy SortBy // sort by field
}
+// Copy returns a copy of the options.
+// Be careful, it's not a deep copy, so `SearchOptions.RepoIDs = {...}` is OK while `SearchOptions.RepoIDs[0] = ...` is not.
+func (o *SearchOptions) Copy(edit ...func(options *SearchOptions)) *SearchOptions {
+ if o == nil {
+ return nil
+ }
+ v := *o
+ for _, e := range edit {
+ e(&v)
+ }
+ return &v
+}
+
type SortBy string
const (