Skip to content

Commit 830ae61

Browse files
lunnytechknowlogick
authored andcommitted
Refactor issue indexer (#5363)
1 parent 094263d commit 830ae61

File tree

22 files changed

+1045
-116
lines changed

22 files changed

+1045
-116
lines changed

Gopkg.lock

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

models/issue.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,12 +183,21 @@ func (issue *Issue) LoadPullRequest() error {
183183
}
184184

185185
func (issue *Issue) loadComments(e Engine) (err error) {
186+
return issue.loadCommentsByType(e, CommentTypeUnknown)
187+
}
188+
189+
// LoadDiscussComments loads discuss comments
190+
func (issue *Issue) LoadDiscussComments() error {
191+
return issue.loadCommentsByType(x, CommentTypeComment)
192+
}
193+
194+
func (issue *Issue) loadCommentsByType(e Engine, tp CommentType) (err error) {
186195
if issue.Comments != nil {
187196
return nil
188197
}
189198
issue.Comments, err = findComments(e, FindCommentsOptions{
190199
IssueID: issue.ID,
191-
Type: CommentTypeUnknown,
200+
Type: tp,
192201
})
193202
return err
194203
}
@@ -681,7 +690,6 @@ func updateIssueCols(e Engine, issue *Issue, cols ...string) error {
681690
if _, err := e.ID(issue.ID).Cols(cols...).Update(issue); err != nil {
682691
return err
683692
}
684-
UpdateIssueIndexerCols(issue.ID, cols...)
685693
return nil
686694
}
687695

@@ -1217,6 +1225,12 @@ func getIssuesByIDs(e Engine, issueIDs []int64) ([]*Issue, error) {
12171225
return issues, e.In("id", issueIDs).Find(&issues)
12181226
}
12191227

1228+
func getIssueIDsByRepoID(e Engine, repoID int64) ([]int64, error) {
1229+
var ids = make([]int64, 0, 10)
1230+
err := e.Table("issue").Where("repo_id = ?", repoID).Find(&ids)
1231+
return ids, err
1232+
}
1233+
12201234
// GetIssuesByIDs return issues with the given IDs.
12211235
func GetIssuesByIDs(issueIDs []int64) ([]*Issue, error) {
12221236
return getIssuesByIDs(x, issueIDs)

models/issue_comment.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,6 +1035,7 @@ func UpdateComment(doer *User, c *Comment, oldContent string) error {
10351035
if err := c.LoadIssue(); err != nil {
10361036
return err
10371037
}
1038+
10381039
if err := c.Issue.LoadAttributes(); err != nil {
10391040
return err
10401041
}
@@ -1093,6 +1094,7 @@ func DeleteComment(doer *User, comment *Comment) error {
10931094
if err := comment.LoadIssue(); err != nil {
10941095
return err
10951096
}
1097+
10961098
if err := comment.Issue.LoadAttributes(); err != nil {
10971099
return err
10981100
}

models/issue_indexer.go

Lines changed: 91 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,60 @@ package models
77
import (
88
"fmt"
99

10-
"code.gitea.io/gitea/modules/indexer"
10+
"code.gitea.io/gitea/modules/indexer/issues"
1111
"code.gitea.io/gitea/modules/log"
1212
"code.gitea.io/gitea/modules/setting"
1313
"code.gitea.io/gitea/modules/util"
1414
)
1515

16-
// issueIndexerUpdateQueue queue of issue ids to be updated
17-
var issueIndexerUpdateQueue chan int64
16+
var (
17+
// issueIndexerUpdateQueue queue of issue ids to be updated
18+
issueIndexerUpdateQueue issues.Queue
19+
issueIndexer issues.Indexer
20+
)
1821

1922
// InitIssueIndexer initialize issue indexer
20-
func InitIssueIndexer() {
21-
indexer.InitIssueIndexer(populateIssueIndexer)
22-
issueIndexerUpdateQueue = make(chan int64, setting.Indexer.UpdateQueueLength)
23-
go processIssueIndexerUpdateQueue()
23+
func InitIssueIndexer() error {
24+
var populate bool
25+
switch setting.Indexer.IssueType {
26+
case "bleve":
27+
issueIndexer = issues.NewBleveIndexer(setting.Indexer.IssuePath)
28+
exist, err := issueIndexer.Init()
29+
if err != nil {
30+
return err
31+
}
32+
populate = !exist
33+
default:
34+
return fmt.Errorf("unknow issue indexer type: %s", setting.Indexer.IssueType)
35+
}
36+
37+
var err error
38+
switch setting.Indexer.IssueIndexerQueueType {
39+
case setting.LevelQueueType:
40+
issueIndexerUpdateQueue, err = issues.NewLevelQueue(
41+
issueIndexer,
42+
setting.Indexer.IssueIndexerQueueDir,
43+
setting.Indexer.IssueIndexerQueueBatchNumber)
44+
if err != nil {
45+
return err
46+
}
47+
case setting.ChannelQueueType:
48+
issueIndexerUpdateQueue = issues.NewChannelQueue(issueIndexer, setting.Indexer.IssueIndexerQueueBatchNumber)
49+
default:
50+
return fmt.Errorf("Unsupported indexer queue type: %v", setting.Indexer.IssueIndexerQueueType)
51+
}
52+
53+
go issueIndexerUpdateQueue.Run()
54+
55+
if populate {
56+
go populateIssueIndexer()
57+
}
58+
59+
return nil
2460
}
2561

2662
// populateIssueIndexer populate the issue indexer with issue data
27-
func populateIssueIndexer() error {
28-
batch := indexer.IssueIndexerBatch()
63+
func populateIssueIndexer() {
2964
for page := 1; ; page++ {
3065
repos, _, err := SearchRepositoryByName(&SearchRepoOptions{
3166
Page: page,
@@ -35,98 +70,79 @@ func populateIssueIndexer() error {
3570
Collaborate: util.OptionalBoolFalse,
3671
})
3772
if err != nil {
38-
return fmt.Errorf("Repositories: %v", err)
73+
log.Error(4, "SearchRepositoryByName: %v", err)
74+
continue
3975
}
4076
if len(repos) == 0 {
41-
return batch.Flush()
77+
return
4278
}
79+
4380
for _, repo := range repos {
44-
issues, err := Issues(&IssuesOptions{
81+
is, err := Issues(&IssuesOptions{
4582
RepoIDs: []int64{repo.ID},
4683
IsClosed: util.OptionalBoolNone,
4784
IsPull: util.OptionalBoolNone,
4885
})
4986
if err != nil {
50-
return err
87+
log.Error(4, "Issues: %v", err)
88+
continue
5189
}
52-
if err = IssueList(issues).LoadComments(); err != nil {
53-
return err
90+
if err = IssueList(is).LoadDiscussComments(); err != nil {
91+
log.Error(4, "LoadComments: %v", err)
92+
continue
5493
}
55-
for _, issue := range issues {
56-
if err := issue.update().AddToFlushingBatch(batch); err != nil {
57-
return err
58-
}
94+
for _, issue := range is {
95+
UpdateIssueIndexer(issue)
5996
}
6097
}
6198
}
6299
}
63100

64-
func processIssueIndexerUpdateQueue() {
65-
batch := indexer.IssueIndexerBatch()
66-
for {
67-
var issueID int64
68-
select {
69-
case issueID = <-issueIndexerUpdateQueue:
70-
default:
71-
// flush whatever updates we currently have, since we
72-
// might have to wait a while
73-
if err := batch.Flush(); err != nil {
74-
log.Error(4, "IssueIndexer: %v", err)
75-
}
76-
issueID = <-issueIndexerUpdateQueue
77-
}
78-
issue, err := GetIssueByID(issueID)
79-
if err != nil {
80-
log.Error(4, "GetIssueByID: %v", err)
81-
} else if err = issue.update().AddToFlushingBatch(batch); err != nil {
82-
log.Error(4, "IssueIndexer: %v", err)
83-
}
84-
}
85-
}
86-
87-
func (issue *Issue) update() indexer.IssueIndexerUpdate {
88-
comments := make([]string, 0, 5)
101+
// UpdateIssueIndexer add/update an issue to the issue indexer
102+
func UpdateIssueIndexer(issue *Issue) {
103+
var comments []string
89104
for _, comment := range issue.Comments {
90105
if comment.Type == CommentTypeComment {
91106
comments = append(comments, comment.Content)
92107
}
93108
}
94-
return indexer.IssueIndexerUpdate{
95-
IssueID: issue.ID,
96-
Data: &indexer.IssueIndexerData{
97-
RepoID: issue.RepoID,
98-
Title: issue.Title,
99-
Content: issue.Content,
100-
Comments: comments,
101-
},
102-
}
109+
issueIndexerUpdateQueue.Push(&issues.IndexerData{
110+
ID: issue.ID,
111+
RepoID: issue.RepoID,
112+
Title: issue.Title,
113+
Content: issue.Content,
114+
Comments: comments,
115+
})
103116
}
104117

105-
// updateNeededCols whether a change to the specified columns requires updating
106-
// the issue indexer
107-
func updateNeededCols(cols []string) bool {
108-
for _, col := range cols {
109-
switch col {
110-
case "name", "content":
111-
return true
112-
}
118+
// DeleteRepoIssueIndexer deletes repo's all issues indexes
119+
func DeleteRepoIssueIndexer(repo *Repository) {
120+
var ids []int64
121+
ids, err := getIssueIDsByRepoID(x, repo.ID)
122+
if err != nil {
123+
log.Error(4, "getIssueIDsByRepoID failed: %v", err)
124+
return
125+
}
126+
127+
if len(ids) <= 0 {
128+
return
113129
}
114-
return false
115-
}
116130

117-
// UpdateIssueIndexerCols update an issue in the issue indexer, given changes
118-
// to the specified columns
119-
func UpdateIssueIndexerCols(issueID int64, cols ...string) {
120-
updateNeededCols(cols)
131+
issueIndexerUpdateQueue.Push(&issues.IndexerData{
132+
IDs: ids,
133+
IsDelete: true,
134+
})
121135
}
122136

123-
// UpdateIssueIndexer add/update an issue to the issue indexer
124-
func UpdateIssueIndexer(issueID int64) {
125-
select {
126-
case issueIndexerUpdateQueue <- issueID:
127-
default:
128-
go func() {
129-
issueIndexerUpdateQueue <- issueID
130-
}()
137+
// SearchIssuesByKeyword search issue ids by keywords and repo id
138+
func SearchIssuesByKeyword(repoID int64, keyword string) ([]int64, error) {
139+
var issueIDs []int64
140+
res, err := issueIndexer.Search(keyword, repoID, 1000, 0)
141+
if err != nil {
142+
return nil, err
143+
}
144+
for _, r := range res.Hits {
145+
issueIDs = append(issueIDs, r.ID)
131146
}
147+
return issueIDs, nil
132148
}

models/issue_list.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44

55
package models
66

7-
import "fmt"
7+
import (
8+
"fmt"
9+
10+
"github.com/go-xorm/builder"
11+
)
812

913
// IssueList defines a list of issues
1014
type IssueList []*Issue
@@ -338,7 +342,7 @@ func (issues IssueList) loadAttachments(e Engine) (err error) {
338342
return nil
339343
}
340344

341-
func (issues IssueList) loadComments(e Engine) (err error) {
345+
func (issues IssueList) loadComments(e Engine, cond builder.Cond) (err error) {
342346
if len(issues) == 0 {
343347
return nil
344348
}
@@ -354,6 +358,7 @@ func (issues IssueList) loadComments(e Engine) (err error) {
354358
rows, err := e.Table("comment").
355359
Join("INNER", "issue", "issue.id = comment.issue_id").
356360
In("issue.id", issuesIDs[:limit]).
361+
Where(cond).
357362
Rows(new(Comment))
358363
if err != nil {
359364
return err
@@ -479,5 +484,10 @@ func (issues IssueList) LoadAttachments() error {
479484

480485
// LoadComments loads comments
481486
func (issues IssueList) LoadComments() error {
482-
return issues.loadComments(x)
487+
return issues.loadComments(x, builder.NewCond())
488+
}
489+
490+
// LoadDiscussComments loads discuss comments
491+
func (issues IssueList) LoadDiscussComments() error {
492+
return issues.loadComments(x, builder.Eq{"comment.type": CommentTypeComment})
483493
}

models/models.go

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212
"net/url"
1313
"os"
1414
"path"
15-
"path/filepath"
1615
"strings"
1716

1817
"code.gitea.io/gitea/modules/log"
@@ -158,19 +157,6 @@ func LoadConfigs() {
158157
DbCfg.SSLMode = sec.Key("SSL_MODE").MustString("disable")
159158
DbCfg.Path = sec.Key("PATH").MustString("data/gitea.db")
160159
DbCfg.Timeout = sec.Key("SQLITE_TIMEOUT").MustInt(500)
161-
162-
sec = setting.Cfg.Section("indexer")
163-
setting.Indexer.IssuePath = sec.Key("ISSUE_INDEXER_PATH").MustString(path.Join(setting.AppDataPath, "indexers/issues.bleve"))
164-
if !filepath.IsAbs(setting.Indexer.IssuePath) {
165-
setting.Indexer.IssuePath = path.Join(setting.AppWorkPath, setting.Indexer.IssuePath)
166-
}
167-
setting.Indexer.RepoIndexerEnabled = sec.Key("REPO_INDEXER_ENABLED").MustBool(false)
168-
setting.Indexer.RepoPath = sec.Key("REPO_INDEXER_PATH").MustString(path.Join(setting.AppDataPath, "indexers/repos.bleve"))
169-
if !filepath.IsAbs(setting.Indexer.RepoPath) {
170-
setting.Indexer.RepoPath = path.Join(setting.AppWorkPath, setting.Indexer.RepoPath)
171-
}
172-
setting.Indexer.UpdateQueueLength = sec.Key("UPDATE_BUFFER_LEN").MustInt(20)
173-
setting.Indexer.MaxIndexerFileSize = sec.Key("MAX_FILE_SIZE").MustInt64(1024 * 1024)
174160
}
175161

176162
// parsePostgreSQLHostPort parses given input in various forms defined in

models/unit_tests.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ func MainTest(m *testing.M, pathToGiteaRoot string) {
4444
fatalTestError("Error creating test engine: %v\n", err)
4545
}
4646

47+
if err = InitIssueIndexer(); err != nil {
48+
fatalTestError("Error InitIssueIndexer: %v\n", err)
49+
}
50+
4751
setting.AppURL = "https://try.gitea.io/"
4852
setting.RunUser = "runuser"
4953
setting.SSH.Port = 3000

0 commit comments

Comments
 (0)