Skip to content

Commit e520dff

Browse files
authored
Improve /api/v1/repos/issues/search by just getting repo ids (#15179) (#15192)
Backport #15179 /api/v1/repos/issues/search is a highly inefficient search which is unfortunately the basis for our dependency searching algorithm. In particular it currently loads all of the repositories and their owners and their primary coding language all of which is immediately thrown away. This PR makes one simple change - just get the IDs. Related #14560 Related #12827 Signed-off-by: Andrew Thornton <[email protected]>
1 parent 2bc7595 commit e520dff

File tree

2 files changed

+72
-38
lines changed

2 files changed

+72
-38
lines changed

models/repo_list.go

Lines changed: 68 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"code.gitea.io/gitea/modules/util"
1313

1414
"xorm.io/builder"
15+
"xorm.io/xorm"
1516
)
1617

1718
// RepositoryListDefaultPageSize is the default number of repositories
@@ -363,6 +364,35 @@ func SearchRepository(opts *SearchRepoOptions) (RepositoryList, int64, error) {
363364

364365
// SearchRepositoryByCondition search repositories by condition
365366
func SearchRepositoryByCondition(opts *SearchRepoOptions, cond builder.Cond, loadAttributes bool) (RepositoryList, int64, error) {
367+
sess, count, err := searchRepositoryByCondition(opts, cond)
368+
if err != nil {
369+
return nil, 0, err
370+
}
371+
defer sess.Close()
372+
373+
defaultSize := 50
374+
if opts.PageSize > 0 {
375+
defaultSize = opts.PageSize
376+
}
377+
repos := make(RepositoryList, 0, defaultSize)
378+
if err := sess.Find(&repos); err != nil {
379+
return nil, 0, fmt.Errorf("Repo: %v", err)
380+
}
381+
382+
if opts.PageSize <= 0 {
383+
count = int64(len(repos))
384+
}
385+
386+
if loadAttributes {
387+
if err := repos.loadAttributes(sess); err != nil {
388+
return nil, 0, fmt.Errorf("LoadAttributes: %v", err)
389+
}
390+
}
391+
392+
return repos, count, nil
393+
}
394+
395+
func searchRepositoryByCondition(opts *SearchRepoOptions, cond builder.Cond) (*xorm.Session, int64, error) {
366396
if opts.Page <= 0 {
367397
opts.Page = 1
368398
}
@@ -376,31 +406,24 @@ func SearchRepositoryByCondition(opts *SearchRepoOptions, cond builder.Cond, loa
376406
}
377407

378408
sess := x.NewSession()
379-
defer sess.Close()
380409

381-
count, err := sess.
382-
Where(cond).
383-
Count(new(Repository))
384-
if err != nil {
385-
return nil, 0, fmt.Errorf("Count: %v", err)
410+
var count int64
411+
if opts.PageSize > 0 {
412+
var err error
413+
count, err = sess.
414+
Where(cond).
415+
Count(new(Repository))
416+
if err != nil {
417+
_ = sess.Close()
418+
return nil, 0, fmt.Errorf("Count: %v", err)
419+
}
386420
}
387421

388-
repos := make(RepositoryList, 0, opts.PageSize)
389422
sess.Where(cond).OrderBy(opts.OrderBy.String())
390423
if opts.PageSize > 0 {
391424
sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize)
392425
}
393-
if err = sess.Find(&repos); err != nil {
394-
return nil, 0, fmt.Errorf("Repo: %v", err)
395-
}
396-
397-
if loadAttributes {
398-
if err = repos.loadAttributes(sess); err != nil {
399-
return nil, 0, fmt.Errorf("LoadAttributes: %v", err)
400-
}
401-
}
402-
403-
return repos, count, nil
426+
return sess, count, nil
404427
}
405428

406429
// accessibleRepositoryCondition takes a user a returns a condition for checking if a repository is accessible
@@ -456,6 +479,33 @@ func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, err
456479
return SearchRepository(opts)
457480
}
458481

482+
// SearchRepositoryIDs takes keyword and part of repository name to search,
483+
// it returns results in given range and number of total results.
484+
func SearchRepositoryIDs(opts *SearchRepoOptions) ([]int64, int64, error) {
485+
opts.IncludeDescription = false
486+
487+
cond := SearchRepositoryCondition(opts)
488+
489+
sess, count, err := searchRepositoryByCondition(opts, cond)
490+
if err != nil {
491+
return nil, 0, err
492+
}
493+
defer sess.Close()
494+
495+
defaultSize := 50
496+
if opts.PageSize > 0 {
497+
defaultSize = opts.PageSize
498+
}
499+
500+
ids := make([]int64, 0, defaultSize)
501+
err = sess.Select("id").Table("repository").Find(&ids)
502+
if opts.PageSize <= 0 {
503+
count = int64(len(ids))
504+
}
505+
506+
return ids, count, err
507+
}
508+
459509
// AccessibleRepoIDsQuery queries accessible repository ids. Usable as a subquery wherever repo ids need to be filtered.
460510
func AccessibleRepoIDsQuery(user *User) *builder.Builder {
461511
// NB: Please note this code needs to still work if user is nil

routers/api/v1/repo/issue.go

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import (
1616
"code.gitea.io/gitea/modules/context"
1717
"code.gitea.io/gitea/modules/convert"
1818
issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
19-
"code.gitea.io/gitea/modules/log"
2019
"code.gitea.io/gitea/modules/notification"
2120
"code.gitea.io/gitea/modules/setting"
2221
api "code.gitea.io/gitea/modules/structs"
@@ -113,11 +112,7 @@ func SearchIssues(ctx *context.APIContext) {
113112
}
114113

115114
// find repos user can access (for issue search)
116-
repoIDs := make([]int64, 0)
117115
opts := &models.SearchRepoOptions{
118-
ListOptions: models.ListOptions{
119-
PageSize: 15,
120-
},
121116
Private: false,
122117
AllPublic: true,
123118
TopicOnly: false,
@@ -132,21 +127,10 @@ func SearchIssues(ctx *context.APIContext) {
132127
opts.AllLimited = true
133128
}
134129

135-
for page := 1; ; page++ {
136-
opts.Page = page
137-
repos, count, err := models.SearchRepositoryByName(opts)
138-
if err != nil {
139-
ctx.Error(http.StatusInternalServerError, "SearchRepositoryByName", err)
140-
return
141-
}
142-
143-
if len(repos) == 0 {
144-
break
145-
}
146-
log.Trace("Processing next %d repos of %d", len(repos), count)
147-
for _, repo := range repos {
148-
repoIDs = append(repoIDs, repo.ID)
149-
}
130+
repoIDs, _, err := models.SearchRepositoryIDs(opts)
131+
if err != nil {
132+
ctx.Error(http.StatusInternalServerError, "SearchRepositoryByName", err)
133+
return
150134
}
151135

152136
var issues []*models.Issue

0 commit comments

Comments
 (0)