aboutsummaryrefslogtreecommitdiffstats
path: root/modules/indexer/issues
diff options
context:
space:
mode:
Diffstat (limited to 'modules/indexer/issues')
-rw-r--r--modules/indexer/issues/db/db.go17
-rw-r--r--modules/indexer/issues/db/options.go8
-rw-r--r--modules/indexer/issues/dboptions.go13
-rw-r--r--modules/indexer/issues/elasticsearch/elasticsearch.go9
-rw-r--r--modules/indexer/issues/indexer.go13
-rw-r--r--modules/indexer/issues/internal/indexer.go8
-rw-r--r--modules/indexer/issues/internal/tests/tests.go49
-rw-r--r--modules/indexer/issues/meilisearch/meilisearch_test.go12
8 files changed, 68 insertions, 61 deletions
diff --git a/modules/indexer/issues/db/db.go b/modules/indexer/issues/db/db.go
index 6124ad2515..50951f9c88 100644
--- a/modules/indexer/issues/db/db.go
+++ b/modules/indexer/issues/db/db.go
@@ -6,6 +6,7 @@ package db
import (
"context"
"strings"
+ "sync"
"code.gitea.io/gitea/models/db"
issue_model "code.gitea.io/gitea/models/issues"
@@ -18,7 +19,7 @@ import (
"xorm.io/builder"
)
-var _ internal.Indexer = &Indexer{}
+var _ internal.Indexer = (*Indexer)(nil)
// Indexer implements Indexer interface to use database's like search
type Indexer struct {
@@ -29,11 +30,9 @@ func (i *Indexer) SupportedSearchModes() []indexer.SearchMode {
return indexer.SearchModesExactWords()
}
-func NewIndexer() *Indexer {
- return &Indexer{
- Indexer: &inner_db.Indexer{},
- }
-}
+var GetIndexer = sync.OnceValue(func() *Indexer {
+ return &Indexer{Indexer: &inner_db.Indexer{}}
+})
// Index dummy function
func (i *Indexer) Index(_ context.Context, _ ...*internal.IndexerData) error {
@@ -122,7 +121,11 @@ func (i *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
}, nil
}
- ids, total, err := issue_model.IssueIDs(ctx, opt, cond)
+ return i.FindWithIssueOptions(ctx, opt, cond)
+}
+
+func (i *Indexer) FindWithIssueOptions(ctx context.Context, opt *issue_model.IssuesOptions, otherConds ...builder.Cond) (*internal.SearchResult, error) {
+ ids, total, err := issue_model.IssueIDs(ctx, opt, otherConds...)
if err != nil {
return nil, err
}
diff --git a/modules/indexer/issues/db/options.go b/modules/indexer/issues/db/options.go
index 3b19d742ba..380a25dc23 100644
--- a/modules/indexer/issues/db/options.go
+++ b/modules/indexer/issues/db/options.go
@@ -6,6 +6,7 @@ package db
import (
"context"
"fmt"
+ "strings"
"code.gitea.io/gitea/models/db"
issue_model "code.gitea.io/gitea/models/issues"
@@ -34,7 +35,11 @@ func ToDBOptions(ctx context.Context, options *internal.SearchOptions) (*issue_m
case internal.SortByDeadlineAsc:
sortType = "nearduedate"
default:
- sortType = "newest"
+ if strings.HasPrefix(string(options.SortBy), issue_model.ScopeSortPrefix) {
+ sortType = string(options.SortBy)
+ } else {
+ sortType = "newest"
+ }
}
// See the comment of issues_model.SearchOptions for the reason why we need to convert
@@ -68,7 +73,6 @@ func ToDBOptions(ctx context.Context, options *internal.SearchOptions) (*issue_m
ExcludedLabelNames: nil,
IncludeMilestones: nil,
SortType: sortType,
- IssueIDs: nil,
UpdatedAfterUnix: options.UpdatedAfterUnix.Value(),
UpdatedBeforeUnix: options.UpdatedBeforeUnix.Value(),
PriorityRepoID: 0,
diff --git a/modules/indexer/issues/dboptions.go b/modules/indexer/issues/dboptions.go
index 4e2dff572a..f17724664d 100644
--- a/modules/indexer/issues/dboptions.go
+++ b/modules/indexer/issues/dboptions.go
@@ -4,12 +4,19 @@
package issues
import (
+ "strings"
+
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
+ "code.gitea.io/gitea/modules/indexer/issues/internal"
"code.gitea.io/gitea/modules/optional"
+ "code.gitea.io/gitea/modules/setting"
)
func ToSearchOptions(keyword string, opts *issues_model.IssuesOptions) *SearchOptions {
+ if opts.IssueIDs != nil {
+ setting.PanicInDevOrTesting("Indexer SearchOptions doesn't support IssueIDs")
+ }
searchOpt := &SearchOptions{
Keyword: keyword,
RepoIDs: opts.RepoIDs,
@@ -95,7 +102,11 @@ func ToSearchOptions(keyword string, opts *issues_model.IssuesOptions) *SearchOp
// Unsupported sort type for search
fallthrough
default:
- searchOpt.SortBy = SortByUpdatedDesc
+ if strings.HasPrefix(opts.SortType, issues_model.ScopeSortPrefix) {
+ searchOpt.SortBy = internal.SortBy(opts.SortType)
+ } else {
+ searchOpt.SortBy = SortByUpdatedDesc
+ }
}
return searchOpt
diff --git a/modules/indexer/issues/elasticsearch/elasticsearch.go b/modules/indexer/issues/elasticsearch/elasticsearch.go
index e3b1b17059..9d627466ef 100644
--- a/modules/indexer/issues/elasticsearch/elasticsearch.go
+++ b/modules/indexer/issues/elasticsearch/elasticsearch.go
@@ -5,7 +5,6 @@ package elasticsearch
import (
"context"
- "fmt"
"strconv"
"strings"
@@ -96,7 +95,7 @@ func (b *Indexer) Index(ctx context.Context, issues ...*internal.IndexerData) er
issue := issues[0]
_, err := b.inner.Client.Index().
Index(b.inner.VersionedIndexName()).
- Id(fmt.Sprintf("%d", issue.ID)).
+ Id(strconv.FormatInt(issue.ID, 10)).
BodyJson(issue).
Do(ctx)
return err
@@ -107,7 +106,7 @@ func (b *Indexer) Index(ctx context.Context, issues ...*internal.IndexerData) er
reqs = append(reqs,
elastic.NewBulkIndexRequest().
Index(b.inner.VersionedIndexName()).
- Id(fmt.Sprintf("%d", issue.ID)).
+ Id(strconv.FormatInt(issue.ID, 10)).
Doc(issue),
)
}
@@ -126,7 +125,7 @@ func (b *Indexer) Delete(ctx context.Context, ids ...int64) error {
} else if len(ids) == 1 {
_, err := b.inner.Client.Delete().
Index(b.inner.VersionedIndexName()).
- Id(fmt.Sprintf("%d", ids[0])).
+ Id(strconv.FormatInt(ids[0], 10)).
Do(ctx)
return err
}
@@ -136,7 +135,7 @@ func (b *Indexer) Delete(ctx context.Context, ids ...int64) error {
reqs = append(reqs,
elastic.NewBulkDeleteRequest().
Index(b.inner.VersionedIndexName()).
- Id(fmt.Sprintf("%d", id)),
+ Id(strconv.FormatInt(id, 10)),
)
}
diff --git a/modules/indexer/issues/indexer.go b/modules/indexer/issues/indexer.go
index 4741235d47..8f25c84b76 100644
--- a/modules/indexer/issues/indexer.go
+++ b/modules/indexer/issues/indexer.go
@@ -103,7 +103,7 @@ func InitIssueIndexer(syncReindex bool) {
log.Fatal("Unable to issueIndexer.Init with connection %s Error: %v", setting.Indexer.IssueConnStr, err)
}
case "db":
- issueIndexer = db.NewIndexer()
+ issueIndexer = db.GetIndexer()
case "meilisearch":
issueIndexer = meilisearch.NewIndexer(setting.Indexer.IssueConnStr, setting.Indexer.IssueConnAuth, setting.Indexer.IssueIndexerName)
existed, err = issueIndexer.Init(ctx)
@@ -217,7 +217,7 @@ func PopulateIssueIndexer(ctx context.Context) error {
return fmt.Errorf("shutdown before completion: %w", ctx.Err())
default:
}
- repos, _, err := repo_model.SearchRepositoryByName(ctx, &repo_model.SearchRepoOptions{
+ repos, _, err := repo_model.SearchRepositoryByName(ctx, repo_model.SearchRepoOptions{
ListOptions: db_model.ListOptions{Page: page, PageSize: repo_model.RepositoryListDefaultPageSize},
OrderBy: db_model.SearchOrderByID,
Private: true,
@@ -291,19 +291,22 @@ func SearchIssues(ctx context.Context, opts *SearchOptions) ([]int64, int64, err
// So if the user creates an issue and list issues immediately, the issue may not be listed because the indexer needs time to index the issue.
// Even worse, the external indexer like elastic search may not be available for a while,
// and the user may not be able to list issues completely until it is available again.
- ix = db.NewIndexer()
+ ix = db.GetIndexer()
}
+
result, err := ix.Search(ctx, opts)
if err != nil {
return nil, 0, err
}
+ return SearchResultToIDSlice(result), result.Total, nil
+}
+func SearchResultToIDSlice(result *internal.SearchResult) []int64 {
ret := make([]int64, 0, len(result.Hits))
for _, hit := range result.Hits {
ret = append(ret, hit.ID)
}
-
- return ret, result.Total, nil
+ return ret
}
// CountIssues counts issues by options. It is a shortcut of SearchIssues(ctx, opts) but only returns the total count.
diff --git a/modules/indexer/issues/internal/indexer.go b/modules/indexer/issues/internal/indexer.go
index 415f442d0c..59c6f48485 100644
--- a/modules/indexer/issues/internal/indexer.go
+++ b/modules/indexer/issues/internal/indexer.go
@@ -5,7 +5,7 @@ package internal
import (
"context"
- "fmt"
+ "errors"
"code.gitea.io/gitea/modules/indexer"
"code.gitea.io/gitea/modules/indexer/internal"
@@ -36,13 +36,13 @@ func (d *dummyIndexer) SupportedSearchModes() []indexer.SearchMode {
}
func (d *dummyIndexer) Index(_ context.Context, _ ...*IndexerData) error {
- return fmt.Errorf("indexer is not ready")
+ return errors.New("indexer is not ready")
}
func (d *dummyIndexer) Delete(_ context.Context, _ ...int64) error {
- return fmt.Errorf("indexer is not ready")
+ return errors.New("indexer is not ready")
}
func (d *dummyIndexer) Search(_ context.Context, _ *SearchOptions) (*SearchResult, error) {
- return nil, fmt.Errorf("indexer is not ready")
+ return nil, errors.New("indexer is not ready")
}
diff --git a/modules/indexer/issues/internal/tests/tests.go b/modules/indexer/issues/internal/tests/tests.go
index 6e92c7885c..7aebbbcd58 100644
--- a/modules/indexer/issues/internal/tests/tests.go
+++ b/modules/indexer/issues/internal/tests/tests.go
@@ -8,7 +8,6 @@
package tests
import (
- "context"
"fmt"
"slices"
"testing"
@@ -40,7 +39,7 @@ func TestIndexer(t *testing.T, indexer internal.Indexer) {
data[v.ID] = v
}
require.NoError(t, indexer.Index(t.Context(), d...))
- require.NoError(t, waitData(indexer, int64(len(data))))
+ waitData(t, indexer, int64(len(data)))
}
defer func() {
@@ -54,13 +53,13 @@ func TestIndexer(t *testing.T, indexer internal.Indexer) {
for _, v := range c.ExtraData {
data[v.ID] = v
}
- require.NoError(t, waitData(indexer, int64(len(data))))
+ waitData(t, indexer, int64(len(data)))
defer func() {
for _, v := range c.ExtraData {
require.NoError(t, indexer.Delete(t.Context(), v.ID))
delete(data, v.ID)
}
- require.NoError(t, waitData(indexer, int64(len(data))))
+ waitData(t, indexer, int64(len(data)))
}()
}
@@ -93,7 +92,7 @@ var cases = []*testIndexerCase{
Name: "default",
SearchOptions: &internal.SearchOptions{},
Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
- assert.Equal(t, len(data), len(result.Hits))
+ assert.Len(t, result.Hits, len(data))
assert.Equal(t, len(data), int(result.Total))
},
},
@@ -526,7 +525,7 @@ var cases = []*testIndexerCase{
SortBy: internal.SortByCreatedDesc,
},
Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
- assert.Equal(t, len(data), len(result.Hits))
+ assert.Len(t, result.Hits, len(data))
assert.Equal(t, len(data), int(result.Total))
for i, v := range result.Hits {
if i < len(result.Hits)-1 {
@@ -542,7 +541,7 @@ var cases = []*testIndexerCase{
SortBy: internal.SortByUpdatedDesc,
},
Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
- assert.Equal(t, len(data), len(result.Hits))
+ assert.Len(t, result.Hits, len(data))
assert.Equal(t, len(data), int(result.Total))
for i, v := range result.Hits {
if i < len(result.Hits)-1 {
@@ -558,7 +557,7 @@ var cases = []*testIndexerCase{
SortBy: internal.SortByCommentsDesc,
},
Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
- assert.Equal(t, len(data), len(result.Hits))
+ assert.Len(t, result.Hits, len(data))
assert.Equal(t, len(data), int(result.Total))
for i, v := range result.Hits {
if i < len(result.Hits)-1 {
@@ -574,7 +573,7 @@ var cases = []*testIndexerCase{
SortBy: internal.SortByDeadlineDesc,
},
Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
- assert.Equal(t, len(data), len(result.Hits))
+ assert.Len(t, result.Hits, len(data))
assert.Equal(t, len(data), int(result.Total))
for i, v := range result.Hits {
if i < len(result.Hits)-1 {
@@ -590,7 +589,7 @@ var cases = []*testIndexerCase{
SortBy: internal.SortByCreatedAsc,
},
Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
- assert.Equal(t, len(data), len(result.Hits))
+ assert.Len(t, result.Hits, len(data))
assert.Equal(t, len(data), int(result.Total))
for i, v := range result.Hits {
if i < len(result.Hits)-1 {
@@ -606,7 +605,7 @@ var cases = []*testIndexerCase{
SortBy: internal.SortByUpdatedAsc,
},
Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
- assert.Equal(t, len(data), len(result.Hits))
+ assert.Len(t, result.Hits, len(data))
assert.Equal(t, len(data), int(result.Total))
for i, v := range result.Hits {
if i < len(result.Hits)-1 {
@@ -622,7 +621,7 @@ var cases = []*testIndexerCase{
SortBy: internal.SortByCommentsAsc,
},
Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
- assert.Equal(t, len(data), len(result.Hits))
+ assert.Len(t, result.Hits, len(data))
assert.Equal(t, len(data), int(result.Total))
for i, v := range result.Hits {
if i < len(result.Hits)-1 {
@@ -638,7 +637,7 @@ var cases = []*testIndexerCase{
SortBy: internal.SortByDeadlineAsc,
},
Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
- assert.Equal(t, len(data), len(result.Hits))
+ assert.Len(t, result.Hits, len(data))
assert.Equal(t, len(data), int(result.Total))
for i, v := range result.Hits {
if i < len(result.Hits)-1 {
@@ -751,22 +750,10 @@ func countIndexerData(data map[int64]*internal.IndexerData, f func(v *internal.I
// waitData waits for the indexer to index all data.
// Some engines like Elasticsearch index data asynchronously, so we need to wait for a while.
-func waitData(indexer internal.Indexer, total int64) error {
- var actual int64
- for i := 0; i < 100; i++ {
- result, err := indexer.Search(context.Background(), &internal.SearchOptions{
- Paginator: &db.ListOptions{
- PageSize: 0,
- },
- })
- if err != nil {
- return err
- }
- actual = result.Total
- if actual == total {
- return nil
- }
- time.Sleep(100 * time.Millisecond)
- }
- return fmt.Errorf("waitData: expected %d, actual %d", total, actual)
+func waitData(t *testing.T, indexer internal.Indexer, total int64) {
+ assert.Eventually(t, func() bool {
+ result, err := indexer.Search(t.Context(), &internal.SearchOptions{Paginator: &db.ListOptions{}})
+ require.NoError(t, err)
+ return result.Total == total
+ }, 10*time.Second, 100*time.Millisecond, "expected total=%d", total)
}
diff --git a/modules/indexer/issues/meilisearch/meilisearch_test.go b/modules/indexer/issues/meilisearch/meilisearch_test.go
index a3a332554a..2fea4004cb 100644
--- a/modules/indexer/issues/meilisearch/meilisearch_test.go
+++ b/modules/indexer/issues/meilisearch/meilisearch_test.go
@@ -74,13 +74,13 @@ func TestConvertHits(t *testing.T) {
}
hits, err := convertHits(validResponse)
assert.NoError(t, err)
- assert.EqualValues(t, []internal.Match{{ID: 11}, {ID: 22}, {ID: 33}}, hits)
+ assert.Equal(t, []internal.Match{{ID: 11}, {ID: 22}, {ID: 33}}, hits)
}
func TestDoubleQuoteKeyword(t *testing.T) {
- assert.EqualValues(t, "", doubleQuoteKeyword(""))
- assert.EqualValues(t, `"a" "b" "c"`, doubleQuoteKeyword("a b c"))
- assert.EqualValues(t, `"a" "d" "g"`, doubleQuoteKeyword("a d g"))
- assert.EqualValues(t, `"a" "d" "g"`, doubleQuoteKeyword("a d g"))
- assert.EqualValues(t, `"a" "d" "g"`, doubleQuoteKeyword(`a "" "d" """g`))
+ assert.Empty(t, doubleQuoteKeyword(""))
+ assert.Equal(t, `"a" "b" "c"`, doubleQuoteKeyword("a b c"))
+ assert.Equal(t, `"a" "d" "g"`, doubleQuoteKeyword("a d g"))
+ assert.Equal(t, `"a" "d" "g"`, doubleQuoteKeyword("a d g"))
+ assert.Equal(t, `"a" "d" "g"`, doubleQuoteKeyword(`a "" "d" """g`))
}