From f233a74b705d23d2c5b69e2d54cb82663b086b53 Mon Sep 17 00:00:00 2001 From: Alexander Emelin Date: Mon, 4 Jul 2022 11:33:07 +0300 Subject: [PATCH] Search: Downgrade Bluge, refactor code (#51560) Co-authored-by: Ryan McKinley --- go.mod | 5 +- go.sum | 7 +- pkg/services/searchV2/bluge.go | 77 ++++++--- pkg/services/searchV2/index.go | 259 ++++++++++++++-------------- pkg/services/searchV2/index_test.go | 166 ++++++++++-------- pkg/services/searchV2/service.go | 8 +- 6 files changed, 287 insertions(+), 235 deletions(-) diff --git a/go.mod b/go.mod index 8f8836a37a2..efe22d55747 100644 --- a/go.mod +++ b/go.mod @@ -240,8 +240,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.4.0 github.com/Azure/go-autorest/autorest/adal v0.9.17 github.com/armon/go-radix v1.0.0 - github.com/blugelabs/bluge v0.2.1 - github.com/blugelabs/bluge_segment_api v0.2.0 + github.com/blugelabs/bluge v0.1.9 github.com/getkin/kin-openapi v0.94.0 github.com/golang-migrate/migrate/v4 v4.7.0 github.com/grafana/dskit v0.0.0-20211011144203-3a88ec0b675f @@ -256,6 +255,7 @@ require ( require ( cloud.google.com/go v0.100.2 // indirect github.com/armon/go-metrics v0.3.10 // indirect + github.com/blugelabs/bluge_segment_api v0.2.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/gosimple/unidecode v1.0.1 // indirect @@ -282,7 +282,6 @@ require ( github.com/blevesearch/snowballstem v0.9.0 // indirect github.com/blevesearch/vellum v1.0.7 // indirect github.com/blugelabs/ice v1.0.0 // indirect - github.com/blugelabs/ice/v2 v2.0.1 // indirect github.com/caio/go-tdigest v3.1.0+incompatible // indirect github.com/chromedp/cdproto v0.0.0-20220208224320-6efb837e6bc2 // indirect github.com/containerd/containerd v1.6.6 // indirect diff --git a/go.sum b/go.sum index b4eb9f79648..1bb9a7c48e9 100644 --- a/go.sum +++ b/go.sum @@ -435,14 +435,13 @@ github.com/blevesearch/snowballstem v0.9.0/go.mod h1:PivSj3JMc8WuaFkTSRDW2SlrulN github.com/blevesearch/vellum v1.0.5/go.mod h1:atE0EH3fvk43zzS7t1YNdNC7DbmcC3uz+eMD5xZ2OyQ= github.com/blevesearch/vellum v1.0.7 h1:+vn8rfyCRHxKVRgDLeR0FAXej2+6mEb5Q15aQE/XESQ= github.com/blevesearch/vellum v1.0.7/go.mod h1:doBZpmRhwTsASB4QdUZANlJvqVAUdUyX0ZK7QJCTeBE= -github.com/blugelabs/bluge v0.2.1 h1:lgd6IhAAIDoq6my9HQOwk3p6xqJBmR49+lpFmpeFHgU= -github.com/blugelabs/bluge v0.2.1/go.mod h1:am1LU9jS8dZgWkRzkGLQN3757EgMs3upWrU2fdN9foE= +github.com/blugelabs/bluge v0.1.9 h1:bPgXlcsWugrXNjzeoLdOnvfJpHsyODKpYaAndayl/SM= +github.com/blugelabs/bluge v0.1.9/go.mod h1:5d7LktUkQgvbh5Bmi6tPWtvo4+6uRTm6gAwP+5z6FqQ= github.com/blugelabs/bluge_segment_api v0.2.0 h1:cCX1Y2y8v0LZ7+EEJ6gH7dW6TtVTW4RhG0vp3R+N2Lo= github.com/blugelabs/bluge_segment_api v0.2.0/go.mod h1:95XA+ZXfRj/IXADm7gZ+iTcWOJPg5jQTY1EReIzl3LA= +github.com/blugelabs/ice v0.2.0/go.mod h1:7foiDf4V83FIYYnGh2LOoRWsbNoCqAAMNgKn879Iyu0= github.com/blugelabs/ice v1.0.0 h1:um7wf9e6jbkTVCrOyQq3tKK43fBMOvLUYxbj3Qtc4eo= github.com/blugelabs/ice v1.0.0/go.mod h1:gNfFPk5zM+yxJROhthxhVQYjpBO9amuxWXJQ2Lo+IbQ= -github.com/blugelabs/ice/v2 v2.0.1 h1:mzHbntLjk2v7eDRgoXCgzOsPKN1Tenu9Svo6l9cTLS4= -github.com/blugelabs/ice/v2 v2.0.1/go.mod h1:QxAWSPNwZwsIqS25c3lbIPFQrVvT1sphf5x5DfMLH5M= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= diff --git a/pkg/services/searchV2/bluge.go b/pkg/services/searchV2/bluge.go index b0473260d77..c65624c7f16 100644 --- a/pkg/services/searchV2/bluge.go +++ b/pkg/services/searchV2/bluge.go @@ -34,10 +34,10 @@ const ( DocumentFieldUpdatedAt = "updated_at" ) -func initIndex(dashboards []dashboard, logger log.Logger, extendDoc ExtendDashboardFunc) (*bluge.Reader, *bluge.Writer, error) { - writer, err := bluge.OpenWriter(bluge.InMemoryOnlyConfig()) +func initOrgIndex(dashboards []dashboard, logger log.Logger, extendDoc ExtendDashboardFunc) (*orgIndex, error) { + dashboardWriter, err := bluge.OpenWriter(bluge.InMemoryOnlyConfig()) if err != nil { - return nil, nil, fmt.Errorf("error opening writer: %v", err) + return nil, fmt.Errorf("error opening writer: %v", err) } // Not closing Writer here since we use it later while processing dashboard change events. @@ -49,7 +49,7 @@ func initIndex(dashboards []dashboard, logger log.Logger, extendDoc ExtendDashbo // In order to reduce memory usage while initial indexing we are limiting // the size of batch here. docsInBatch := 0 - maxBatchSize := 300 + maxBatchSize := 100 flushIfRequired := func(force bool) error { docsInBatch++ @@ -57,7 +57,7 @@ func initIndex(dashboards []dashboard, logger log.Logger, extendDoc ExtendDashbo if !needFlush { return nil } - err := writer.Batch(batch) + err := dashboardWriter.Batch(batch) if err != nil { return err } @@ -74,11 +74,11 @@ func initIndex(dashboards []dashboard, logger log.Logger, extendDoc ExtendDashbo } doc := getFolderDashboardDoc(dash) if err := extendDoc(dash.uid, doc); err != nil { - return nil, nil, err + return nil, err } batch.Insert(doc) if err := flushIfRequired(false); err != nil { - return nil, nil, err + return nil, err } uid := dash.uid if uid == "" { @@ -96,11 +96,11 @@ func initIndex(dashboards []dashboard, logger log.Logger, extendDoc ExtendDashbo location := folderUID doc := getNonFolderDashboardDoc(dash, location) if err := extendDoc(dash.uid, doc); err != nil { - return nil, nil, err + return nil, err } batch.Insert(doc) if err := flushIfRequired(false); err != nil { - return nil, nil, err + return nil, err } // Index each panel in dashboard. @@ -109,25 +109,27 @@ func initIndex(dashboards []dashboard, logger log.Logger, extendDoc ExtendDashbo } location += dash.uid docs := getDashboardPanelDocs(dash, location) + for _, panelDoc := range docs { batch.Insert(panelDoc) if err := flushIfRequired(false); err != nil { - return nil, nil, err + return nil, err } } } + + // Flush docs in batch with force as we are in the end. if err := flushIfRequired(true); err != nil { - return nil, nil, err + return nil, err } + logger.Info("Finish inserting docs into index", "elapsed", time.Since(label)) - - reader, err := writer.Reader() - if err != nil { - return nil, nil, err - } - logger.Info("Finish building index", "totalElapsed", time.Since(start)) - return reader, writer, err + return &orgIndex{ + writers: map[indexType]*bluge.Writer{ + indexTypeDashboard: dashboardWriter, + }, + }, err } func getFolderDashboardDoc(dash dashboard) *bluge.Document { @@ -244,8 +246,15 @@ func newSearchDocument(uid string, name string, descr string, url string) *bluge return doc } -func getDashboardPanelIDs(reader *bluge.Reader, panelLocation string) ([]string, error) { +func getDashboardPanelIDs(index *orgIndex, panelLocation string) ([]string, error) { var panelIDs []string + + reader, cancel, err := index.readerForIndex(indexTypeDashboard) + if err != nil { + return nil, err + } + defer cancel() + fullQuery := bluge.NewBooleanQuery() fullQuery.AddMust(bluge.NewTermQuery(panelLocation).SetField(documentFieldLocation)) fullQuery.AddMust(bluge.NewTermQuery(string(entityKindPanel)).SetField(documentFieldKind)) @@ -272,14 +281,21 @@ func getDashboardPanelIDs(reader *bluge.Reader, panelLocation string) ([]string, return panelIDs, err } -func getDocsIDsByLocationPrefix(reader *bluge.Reader, prefix string) ([]string, error) { +func getDocsIDsByLocationPrefix(index *orgIndex, prefix string) ([]string, error) { var ids []string + + reader, cancel, err := index.readerForIndex(indexTypeDashboard) + if err != nil { + return nil, fmt.Errorf("error getting reader: %w", err) + } + defer cancel() + fullQuery := bluge.NewBooleanQuery() fullQuery.AddMust(bluge.NewPrefixQuery(prefix).SetField(documentFieldLocation)) req := bluge.NewAllMatches(fullQuery) documentMatchIterator, err := reader.Search(context.Background(), req) if err != nil { - return nil, err + return nil, fmt.Errorf("error search: %w", err) } match, err := documentMatchIterator.Next() for err == nil && match != nil { @@ -299,9 +315,16 @@ func getDocsIDsByLocationPrefix(reader *bluge.Reader, prefix string) ([]string, return ids, err } -func getDashboardLocation(reader *bluge.Reader, dashboardUID string) (string, bool, error) { +func getDashboardLocation(index *orgIndex, dashboardUID string) (string, bool, error) { var dashboardLocation string var found bool + + reader, cancel, err := index.readerForIndex(indexTypeDashboard) + if err != nil { + return "", false, err + } + defer cancel() + fullQuery := bluge.NewBooleanQuery() fullQuery.AddMust(bluge.NewTermQuery(dashboardUID).SetField(documentFieldUID)) fullQuery.AddMust(bluge.NewTermQuery(string(entityKindDashboard)).SetField(documentFieldKind)) @@ -334,7 +357,7 @@ func getDashboardLocation(reader *bluge.Reader, dashboardUID string) (string, bo func doSearchQuery( ctx context.Context, logger log.Logger, - reader *bluge.Reader, + index *orgIndex, filter ResourceFilter, q DashboardQuery, extender QueryExtender, @@ -343,6 +366,14 @@ func doSearchQuery( response := &backend.DataResponse{} header := &customMeta{} + reader, cancel, err := index.readerForIndex(indexTypeDashboard) + if err != nil { + logger.Error("error getting reader for dashboard index: %v", err) + response.Error = err + return response + } + defer cancel() + hasConstraints := false fullQuery := bluge.NewBooleanQuery() fullQuery.AddMust(newPermissionFilter(filter, logger)) diff --git a/pkg/services/searchV2/index.go b/pkg/services/searchV2/index.go index 44cf9b92c29..6cbe0916d0b 100644 --- a/pkg/services/searchV2/index.go +++ b/pkg/services/searchV2/index.go @@ -59,11 +59,32 @@ type buildSignal struct { done chan error } -type dashboardIndex struct { +type orgIndex struct { + writers map[indexType]*bluge.Writer +} + +type indexType string + +const ( + indexTypeDashboard indexType = "dashboard" +) + +func (i *orgIndex) writerForIndex(idxType indexType) *bluge.Writer { + return i.writers[idxType] +} + +func (i *orgIndex) readerForIndex(idxType indexType) (*bluge.Reader, func(), error) { + reader, err := i.writers[idxType].Reader() + if err != nil { + return nil, nil, err + } + return reader, func() { _ = reader.Close() }, nil +} + +type searchIndex struct { mu sync.RWMutex loader dashboardLoader - perOrgReader map[int64]*bluge.Reader // orgId -> bluge reader - perOrgWriter map[int64]*bluge.Writer // orgId -> bluge writer + perOrgIndex map[int64]*orgIndex eventStore eventStore logger log.Logger buildSignals chan buildSignal @@ -72,13 +93,12 @@ type dashboardIndex struct { syncCh chan chan struct{} } -func newDashboardIndex(dashLoader dashboardLoader, evStore eventStore, extender DocumentExtender, folderIDs folderUIDLookup) *dashboardIndex { - return &dashboardIndex{ +func newSearchIndex(dashLoader dashboardLoader, evStore eventStore, extender DocumentExtender, folderIDs folderUIDLookup) *searchIndex { + return &searchIndex{ loader: dashLoader, eventStore: evStore, - perOrgReader: map[int64]*bluge.Reader{}, - perOrgWriter: map[int64]*bluge.Writer{}, - logger: log.New("dashboardIndex"), + perOrgIndex: map[int64]*orgIndex{}, + logger: log.New("searchIndex"), buildSignals: make(chan buildSignal), extender: extender, folderIdLookup: folderIDs, @@ -86,7 +106,7 @@ func newDashboardIndex(dashLoader dashboardLoader, evStore eventStore, extender } } -func (i *dashboardIndex) sync(ctx context.Context) error { +func (i *searchIndex) sync(ctx context.Context) error { doneCh := make(chan struct{}, 1) select { case i.syncCh <- doneCh: @@ -101,7 +121,7 @@ func (i *dashboardIndex) sync(ctx context.Context) error { } } -func (i *dashboardIndex) run(ctx context.Context, orgIDs []int64, reIndexSignalCh chan struct{}) error { +func (i *searchIndex) run(ctx context.Context, orgIDs []int64, reIndexSignalCh chan struct{}) error { reIndexInterval := 5 * time.Minute fullReIndexTimer := time.NewTimer(reIndexInterval) defer fullReIndexTimer.Stop() @@ -147,7 +167,7 @@ func (i *dashboardIndex) run(ctx context.Context, orgIDs []int64, reIndexSignalC case signal := <-i.buildSignals: // When search read request meets new not-indexed org we build index for it. i.mu.RLock() - _, ok := i.perOrgWriter[signal.orgID] + _, ok := i.perOrgIndex[signal.orgID] if ok { // Index for org already exists, do nothing. i.mu.RUnlock() @@ -206,7 +226,7 @@ func (i *dashboardIndex) run(ctx context.Context, orgIDs []int64, reIndexSignalC } } -func (i *dashboardIndex) buildInitialIndexes(ctx context.Context, orgIDs []int64) error { +func (i *searchIndex) buildInitialIndexes(ctx context.Context, orgIDs []int64) error { started := time.Now() i.logger.Info("Start building in-memory indexes") for _, orgID := range orgIDs { @@ -219,7 +239,7 @@ func (i *dashboardIndex) buildInitialIndexes(ctx context.Context, orgIDs []int64 return nil } -func (i *dashboardIndex) buildInitialIndex(ctx context.Context, orgID int64) error { +func (i *searchIndex) buildInitialIndex(ctx context.Context, orgID int64) error { debugCtx, debugCtxCancel := context.WithCancel(ctx) if os.Getenv("GF_SEARCH_DEBUG") != "" { go i.debugResourceUsage(debugCtx, 200*time.Millisecond) @@ -284,7 +304,7 @@ func getProcessCPU(currentPid int) (float64, error) { return 0, errors.New("process not found") } -func (i *dashboardIndex) debugResourceUsage(ctx context.Context, frequency time.Duration) { +func (i *searchIndex) debugResourceUsage(ctx context.Context, frequency time.Duration) { var maxHeapInuse uint64 var maxSys uint64 @@ -326,8 +346,14 @@ func (i *dashboardIndex) debugResourceUsage(ctx context.Context, frequency time. } } -func (i *dashboardIndex) reportSizeOfIndexDiskBackup(orgID int64) { - reader, _ := i.getOrgReader(orgID) +func (i *searchIndex) reportSizeOfIndexDiskBackup(orgID int64) { + index, _ := i.getOrgIndex(orgID) + reader, cancel, err := index.readerForIndex(indexTypeDashboard) + if err != nil { + i.logger.Warn("Error getting reader", "error", err) + return + } + defer cancel() // create a temp directory to store the index tmpDir, err := ioutil.TempDir("", "grafana.dashboard_index") @@ -343,8 +369,8 @@ func (i *dashboardIndex) reportSizeOfIndexDiskBackup(orgID int64) { } }() - cancel := make(chan struct{}) - err = reader.Backup(tmpDir, cancel) + cancelCh := make(chan struct{}) + err = reader.Backup(tmpDir, cancelCh) if err != nil { i.logger.Error("can't create index disk backup", "error", err) return @@ -359,7 +385,7 @@ func (i *dashboardIndex) reportSizeOfIndexDiskBackup(orgID int64) { i.logger.Warn("Size of index disk backup", "size", formatBytes(uint64(size))) } -func (i *dashboardIndex) buildOrgIndex(ctx context.Context, orgID int64) (int, error) { +func (i *searchIndex) buildOrgIndex(ctx context.Context, orgID int64) (int, error) { started := time.Now() ctx, cancel := context.WithTimeout(ctx, time.Minute) defer cancel() @@ -373,7 +399,7 @@ func (i *dashboardIndex) buildOrgIndex(ctx context.Context, orgID int64) (int, e i.logger.Info("Finish loading org dashboards", "elapsed", orgSearchIndexLoadTime, "orgId", orgID) dashboardExtender := i.extender.GetDashboardExtender(orgID) - reader, writer, err := initIndex(dashboards, i.logger, dashboardExtender) + index, err := initOrgIndex(dashboards, i.logger, dashboardExtender) if err != nil { return 0, fmt.Errorf("error initializing index: %w", err) } @@ -388,31 +414,34 @@ func (i *dashboardIndex) buildOrgIndex(ctx context.Context, orgID int64) (int, e "orgSearchDashboardCount", len(dashboards)) i.mu.Lock() - if oldReader, ok := i.perOrgReader[orgID]; ok { - _ = oldReader.Close() + if oldIndex, ok := i.perOrgIndex[orgID]; ok { + for _, w := range oldIndex.writers { + _ = w.Close() + } } - if oldWriter, ok := i.perOrgWriter[orgID]; ok { - _ = oldWriter.Close() - } - i.perOrgReader[orgID] = reader - i.perOrgWriter[orgID] = writer + i.perOrgIndex[orgID] = index i.mu.Unlock() if orgID == 1 { - go updateUsageStats(context.Background(), reader, i.logger) + go func() { + if reader, cancel, err := index.readerForIndex(indexTypeDashboard); err == nil { + defer cancel() + updateUsageStats(context.Background(), reader, i.logger) + } + }() } return len(dashboards), nil } -func (i *dashboardIndex) getOrgReader(orgID int64) (*bluge.Reader, bool) { +func (i *searchIndex) getOrgIndex(orgID int64) (*orgIndex, bool) { i.mu.RLock() defer i.mu.RUnlock() - r, ok := i.perOrgReader[orgID] + r, ok := i.perOrgIndex[orgID] return r, ok } -func (i *dashboardIndex) getOrCreateReader(ctx context.Context, orgID int64) (*bluge.Reader, error) { - reader, ok := i.getOrgReader(orgID) +func (i *searchIndex) getOrCreateOrgIndex(ctx context.Context, orgID int64) (*orgIndex, error) { + index, ok := i.getOrgIndex(orgID) if !ok { // For non-main organization indexes are built lazily. // If we don't have an index then we are blocking here until an index for @@ -433,22 +462,15 @@ func (i *dashboardIndex) getOrCreateReader(ctx context.Context, orgID int64) (*b case <-ctx.Done(): return nil, ctx.Err() } - reader, _ = i.getOrgReader(orgID) + index, _ = i.getOrgIndex(orgID) } - return reader, nil + return index, nil } -func (i *dashboardIndex) getOrgWriter(orgID int64) (*bluge.Writer, bool) { +func (i *searchIndex) reIndexFromScratch(ctx context.Context) { i.mu.RLock() - defer i.mu.RUnlock() - w, ok := i.perOrgWriter[orgID] - return w, ok -} - -func (i *dashboardIndex) reIndexFromScratch(ctx context.Context) { - i.mu.RLock() - orgIDs := make([]int64, 0, len(i.perOrgWriter)) - for orgID := range i.perOrgWriter { + orgIDs := make([]int64, 0, len(i.perOrgIndex)) + for orgID := range i.perOrgIndex { orgIDs = append(orgIDs, orgID) } i.mu.RUnlock() @@ -462,7 +484,7 @@ func (i *dashboardIndex) reIndexFromScratch(ctx context.Context) { } } -func (i *dashboardIndex) applyIndexUpdates(ctx context.Context, lastEventID int64) int64 { +func (i *searchIndex) applyIndexUpdates(ctx context.Context, lastEventID int64) int64 { events, err := i.eventStore.GetAllEventsAfter(context.Background(), lastEventID) if err != nil { i.logger.Error("can't load events", "error", err) @@ -484,7 +506,7 @@ func (i *dashboardIndex) applyIndexUpdates(ctx context.Context, lastEventID int6 return lastEventID } -func (i *dashboardIndex) applyEventOnIndex(ctx context.Context, e *store.EntityEvent) error { +func (i *searchIndex) applyEventOnIndex(ctx context.Context, e *store.EntityEvent) error { i.logger.Debug("processing event", "event", e) if !strings.HasPrefix(e.EntityId, "database/") { @@ -508,9 +530,9 @@ func (i *dashboardIndex) applyEventOnIndex(ctx context.Context, e *store.EntityE return i.applyEvent(ctx, orgID, kind, uid, e.EventType) } -func (i *dashboardIndex) applyEvent(ctx context.Context, orgID int64, kind store.EntityType, uid string, _ store.EntityEventType) error { +func (i *searchIndex) applyEvent(ctx context.Context, orgID int64, kind store.EntityType, uid string, _ store.EntityEventType) error { i.mu.Lock() - _, ok := i.perOrgWriter[orgID] + _, ok := i.perOrgIndex[orgID] if !ok { // Skip event for org not yet indexed. i.mu.Unlock() @@ -527,49 +549,39 @@ func (i *dashboardIndex) applyEvent(ctx context.Context, orgID int64, kind store i.mu.Lock() defer i.mu.Unlock() - writer, ok := i.perOrgWriter[orgID] + index, ok := i.perOrgIndex[orgID] if !ok { // Skip event for org not yet fully indexed. return nil } - // TODO: should we release index lock while performing removeDashboard/updateDashboard? - reader, ok := i.perOrgReader[orgID] - if !ok { - // Skip event for org not yet fully indexed. - return nil - } - - var newReader *bluge.Reader // In the future we can rely on operation types to reduce work here. if len(dbDashboards) == 0 { switch kind { case store.EntityTypeDashboard: - newReader, err = i.removeDashboard(ctx, writer, reader, uid) + err = i.removeDashboard(ctx, index, uid) case store.EntityTypeFolder: - newReader, err = i.removeFolder(ctx, writer, reader, uid) + err = i.removeFolder(ctx, index, uid) default: return nil } } else { - newReader, err = i.updateDashboard(ctx, orgID, writer, reader, dbDashboards[0]) + err = i.updateDashboard(ctx, orgID, index, dbDashboards[0]) } if err != nil { return err } - _ = reader.Close() - i.perOrgReader[orgID] = newReader return nil } -func (i *dashboardIndex) removeDashboard(_ context.Context, writer *bluge.Writer, reader *bluge.Reader, dashboardUID string) (*bluge.Reader, error) { - dashboardLocation, ok, err := getDashboardLocation(reader, dashboardUID) +func (i *searchIndex) removeDashboard(_ context.Context, index *orgIndex, dashboardUID string) error { + dashboardLocation, ok, err := getDashboardLocation(index, dashboardUID) if err != nil { - return nil, err + return err } if !ok { // No dashboard, nothing to remove. - return reader, nil + return nil } // Find all panel docs to remove with dashboard. @@ -577,40 +589,35 @@ func (i *dashboardIndex) removeDashboard(_ context.Context, writer *bluge.Writer if dashboardLocation != "" { panelLocation = dashboardLocation + "/" + dashboardUID } - panelIDs, err := getDocsIDsByLocationPrefix(reader, panelLocation) + panelIDs, err := getDocsIDsByLocationPrefix(index, panelLocation) if err != nil { - return nil, err + return err } + writer := index.writerForIndex(indexTypeDashboard) + batch := bluge.NewBatch() batch.Delete(bluge.NewDocument(dashboardUID).ID()) for _, panelID := range panelIDs { batch.Delete(bluge.NewDocument(panelID).ID()) } - err = writer.Batch(batch) - if err != nil { - return nil, err - } - - return writer.Reader() + return writer.Batch(batch) } -func (i *dashboardIndex) removeFolder(_ context.Context, writer *bluge.Writer, reader *bluge.Reader, folderUID string) (*bluge.Reader, error) { - ids, err := getDocsIDsByLocationPrefix(reader, folderUID) +func (i *searchIndex) removeFolder(_ context.Context, index *orgIndex, folderUID string) error { + ids, err := getDocsIDsByLocationPrefix(index, folderUID) if err != nil { - return nil, err + return fmt.Errorf("error getting by location prefix: %w", err) } + batch := bluge.NewBatch() batch.Delete(bluge.NewDocument(folderUID).ID()) for _, id := range ids { batch.Delete(bluge.NewDocument(id).ID()) } - err = writer.Batch(batch) - if err != nil { - return nil, err - } - return writer.Reader() + writer := index.writerForIndex(indexTypeDashboard) + return writer.Batch(batch) } func stringInSlice(str string, slice []string) bool { @@ -622,67 +629,65 @@ func stringInSlice(str string, slice []string) bool { return false } -func (i *dashboardIndex) updateDashboard(ctx context.Context, orgID int64, writer *bluge.Writer, reader *bluge.Reader, dash dashboard) (*bluge.Reader, error) { - batch := bluge.NewBatch() - +func (i *searchIndex) updateDashboard(ctx context.Context, orgID int64, index *orgIndex, dash dashboard) error { extendDoc := i.extender.GetDashboardExtender(orgID, dash.uid) + writer := index.writerForIndex(indexTypeDashboard) + var doc *bluge.Document if dash.isFolder { doc = getFolderDashboardDoc(dash) if err := extendDoc(dash.uid, doc); err != nil { - return nil, err + return err } + return writer.Update(doc.ID(), doc) + } + + batch := bluge.NewBatch() + + var folderUID string + if dash.folderID == 0 { + folderUID = "general" } else { - var folderUID string - if dash.folderID == 0 { - folderUID = "general" - } else { - var err error - folderUID, err = i.folderIdLookup(ctx, dash.folderID) - if err != nil { - return nil, err - } - } - - location := folderUID - doc = getNonFolderDashboardDoc(dash, location) - if err := extendDoc(dash.uid, doc); err != nil { - return nil, err - } - - var actualPanelIDs []string - - if location != "" { - location += "/" - } - location += dash.uid - panelDocs := getDashboardPanelDocs(dash, location) - for _, panelDoc := range panelDocs { - actualPanelIDs = append(actualPanelIDs, string(panelDoc.ID().Term())) - batch.Update(panelDoc.ID(), panelDoc) - } - - indexedPanelIDs, err := getDashboardPanelIDs(reader, location) + var err error + folderUID, err = i.folderIdLookup(ctx, dash.folderID) if err != nil { - return nil, err + return err } + } - for _, panelID := range indexedPanelIDs { - if !stringInSlice(panelID, actualPanelIDs) { - batch.Delete(bluge.NewDocument(panelID).ID()) - } + location := folderUID + doc = getNonFolderDashboardDoc(dash, location) + if err := extendDoc(dash.uid, doc); err != nil { + return err + } + + var actualPanelIDs []string + + if location != "" { + location += "/" + } + location += dash.uid + panelDocs := getDashboardPanelDocs(dash, location) + for _, panelDoc := range panelDocs { + actualPanelIDs = append(actualPanelIDs, string(panelDoc.ID().Term())) + batch.Update(panelDoc.ID(), panelDoc) + } + + indexedPanelIDs, err := getDashboardPanelIDs(index, location) + if err != nil { + return err + } + + for _, panelID := range indexedPanelIDs { + if !stringInSlice(panelID, actualPanelIDs) { + batch.Delete(bluge.NewDocument(panelID).ID()) } } batch.Update(doc.ID(), doc) - err := writer.Batch(batch) - if err != nil { - return nil, err - } - - return writer.Reader() + return writer.Batch(batch) } type sqlDashboardLoader struct { diff --git a/pkg/services/searchV2/index_test.go b/pkg/services/searchV2/index_test.go index bd5c1d513a2..972899b6788 100644 --- a/pkg/services/searchV2/index_test.go +++ b/pkg/services/searchV2/index_test.go @@ -37,17 +37,29 @@ var testDisallowAllFilter = func(uid string) bool { var testOrgID int64 = 1 -func initTestIndexFromDashes(t *testing.T, dashboards []dashboard) (*dashboardIndex, *bluge.Reader, *bluge.Writer) { +func initTestOrgIndexFromDashes(t *testing.T, dashboards []dashboard) *orgIndex { + t.Helper() + searchIdx := initTestIndexFromDashesExtended(t, dashboards, &NoopDocumentExtender{}) + return searchIdx.perOrgIndex[testOrgID] +} + +func initTestOrgIndexFromDashesExtended(t *testing.T, dashboards []dashboard, extender DocumentExtender) *orgIndex { + t.Helper() + searchIdx := initTestIndexFromDashesExtended(t, dashboards, extender) + return searchIdx.perOrgIndex[testOrgID] +} + +func initTestIndexFromDashes(t *testing.T, dashboards []dashboard) *searchIndex { t.Helper() return initTestIndexFromDashesExtended(t, dashboards, &NoopDocumentExtender{}) } -func initTestIndexFromDashesExtended(t *testing.T, dashboards []dashboard, extender DocumentExtender) (*dashboardIndex, *bluge.Reader, *bluge.Writer) { +func initTestIndexFromDashesExtended(t *testing.T, dashboards []dashboard, extender DocumentExtender) *searchIndex { t.Helper() dashboardLoader := &testDashboardLoader{ dashboards: dashboards, } - index := newDashboardIndex( + index := newSearchIndex( dashboardLoader, &store.MockEntityEventsService{}, extender, @@ -56,21 +68,17 @@ func initTestIndexFromDashesExtended(t *testing.T, dashboards []dashboard, exten numDashboards, err := index.buildOrgIndex(context.Background(), testOrgID) require.NoError(t, err) require.Equal(t, len(dashboardLoader.dashboards), numDashboards) - reader, ok := index.getOrgReader(testOrgID) - require.True(t, ok) - writer, ok := index.getOrgWriter(testOrgID) - require.True(t, ok) - return index, reader, writer + return index } -func checkSearchResponse(t *testing.T, fileName string, reader *bluge.Reader, filter ResourceFilter, query DashboardQuery) { +func checkSearchResponse(t *testing.T, fileName string, index *orgIndex, filter ResourceFilter, query DashboardQuery) { t.Helper() - checkSearchResponseExtended(t, fileName, reader, filter, query, &NoopQueryExtender{}) + checkSearchResponseExtended(t, fileName, index, filter, query, &NoopQueryExtender{}) } -func checkSearchResponseExtended(t *testing.T, fileName string, reader *bluge.Reader, filter ResourceFilter, query DashboardQuery, extender QueryExtender) { +func checkSearchResponseExtended(t *testing.T, fileName string, index *orgIndex, filter ResourceFilter, query DashboardQuery, extender QueryExtender) { t.Helper() - resp := doSearchQuery(context.Background(), testLogger, reader, filter, query, extender, "/pfix") + resp := doSearchQuery(context.Background(), testLogger, index, filter, query, extender, "/pfix") experimental.CheckGoldenJSONResponse(t, "testdata", fileName, resp, true) } @@ -93,15 +101,15 @@ var testDashboards = []dashboard{ func TestDashboardIndex(t *testing.T) { t.Run("basic-search", func(t *testing.T) { - _, reader, _ := initTestIndexFromDashes(t, testDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), reader, testAllowAllFilter, + index := initTestOrgIndexFromDashes(t, testDashboards) + checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, DashboardQuery{Query: "boom"}, ) }) t.Run("basic-filter", func(t *testing.T) { - _, reader, _ := initTestIndexFromDashes(t, testDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), reader, testDisallowAllFilter, + index := initTestOrgIndexFromDashes(t, testDashboards) + checkSearchResponse(t, filepath.Base(t.Name()), index, testDisallowAllFilter, DashboardQuery{Query: "boom"}, ) }) @@ -109,20 +117,22 @@ func TestDashboardIndex(t *testing.T) { func TestDashboardIndexUpdates(t *testing.T) { t.Run("dashboard-delete", func(t *testing.T) { - index, reader, writer := initTestIndexFromDashes(t, testDashboards) - - newReader, err := index.removeDashboard(context.Background(), writer, reader, "2") + index := initTestIndexFromDashes(t, testDashboards) + orgIdx, ok := index.getOrgIndex(testOrgID) + require.True(t, ok) + err := index.removeDashboard(context.Background(), orgIdx, "2") require.NoError(t, err) - - checkSearchResponse(t, filepath.Base(t.Name()), newReader, testAllowAllFilter, + checkSearchResponse(t, filepath.Base(t.Name()), orgIdx, testAllowAllFilter, DashboardQuery{Query: "boom"}, ) }) t.Run("dashboard-create", func(t *testing.T) { - index, reader, writer := initTestIndexFromDashes(t, testDashboards) + index := initTestIndexFromDashes(t, testDashboards) + orgIdx, ok := index.getOrgIndex(testOrgID) + require.True(t, ok) - newReader, err := index.updateDashboard(context.Background(), testOrgID, writer, reader, dashboard{ + err := index.updateDashboard(context.Background(), testOrgID, orgIdx, dashboard{ id: 3, uid: "3", info: &extract.DashboardInfo{ @@ -131,15 +141,17 @@ func TestDashboardIndexUpdates(t *testing.T) { }) require.NoError(t, err) - checkSearchResponse(t, filepath.Base(t.Name()), newReader, testAllowAllFilter, + checkSearchResponse(t, filepath.Base(t.Name()), orgIdx, testAllowAllFilter, DashboardQuery{Query: "created"}, ) }) t.Run("dashboard-update", func(t *testing.T) { - index, reader, writer := initTestIndexFromDashes(t, testDashboards) + index := initTestIndexFromDashes(t, testDashboards) + orgIdx, ok := index.getOrgIndex(testOrgID) + require.True(t, ok) - newReader, err := index.updateDashboard(context.Background(), testOrgID, writer, reader, dashboard{ + err := index.updateDashboard(context.Background(), testOrgID, orgIdx, dashboard{ id: 2, uid: "2", info: &extract.DashboardInfo{ @@ -148,7 +160,7 @@ func TestDashboardIndexUpdates(t *testing.T) { }) require.NoError(t, err) - checkSearchResponse(t, filepath.Base(t.Name()), newReader, testAllowAllFilter, + checkSearchResponse(t, filepath.Base(t.Name()), orgIdx, testAllowAllFilter, DashboardQuery{Query: "nginx"}, ) }) @@ -231,15 +243,15 @@ func TestDashboardIndexSort(t *testing.T) { } t.Run("sort-asc", func(t *testing.T) { - _, reader, _ := initTestIndexFromDashesExtended(t, testSortDashboards, extender.GetDocumentExtender()) - checkSearchResponseExtended(t, filepath.Base(t.Name()), reader, testAllowAllFilter, + index := initTestOrgIndexFromDashesExtended(t, testSortDashboards, extender.GetDocumentExtender()) + checkSearchResponseExtended(t, filepath.Base(t.Name()), index, testAllowAllFilter, DashboardQuery{Query: "*", Sort: "test"}, extender.GetQueryExtender(), ) }) t.Run("sort-desc", func(t *testing.T) { - _, reader, _ := initTestIndexFromDashesExtended(t, testSortDashboards, extender.GetDocumentExtender()) - checkSearchResponseExtended(t, filepath.Base(t.Name()), reader, testAllowAllFilter, + index := initTestOrgIndexFromDashesExtended(t, testSortDashboards, extender.GetDocumentExtender()) + checkSearchResponseExtended(t, filepath.Base(t.Name()), index, testAllowAllFilter, DashboardQuery{Query: "*", Sort: "-test"}, extender.GetQueryExtender(), ) }) @@ -264,29 +276,29 @@ var testPrefixDashboards = []dashboard{ func TestDashboardIndex_PrefixSearch(t *testing.T) { t.Run("prefix-search-beginning", func(t *testing.T) { - _, reader, _ := initTestIndexFromDashes(t, testPrefixDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), reader, testAllowAllFilter, + index := initTestOrgIndexFromDashes(t, testPrefixDashboards) + checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, DashboardQuery{Query: "Arch"}, ) }) t.Run("prefix-search-middle", func(t *testing.T) { - _, reader, _ := initTestIndexFromDashes(t, testPrefixDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), reader, testAllowAllFilter, + index := initTestOrgIndexFromDashes(t, testPrefixDashboards) + checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, DashboardQuery{Query: "Syn"}, ) }) t.Run("prefix-search-beginning-lower", func(t *testing.T) { - _, reader, _ := initTestIndexFromDashes(t, testPrefixDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), reader, testAllowAllFilter, + index := initTestOrgIndexFromDashes(t, testPrefixDashboards) + checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, DashboardQuery{Query: "arch"}, ) }) t.Run("prefix-search-middle-lower", func(t *testing.T) { - _, reader, _ := initTestIndexFromDashes(t, testPrefixDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), reader, testAllowAllFilter, + index := initTestOrgIndexFromDashes(t, testPrefixDashboards) + checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, DashboardQuery{Query: "syn"}, ) }) @@ -294,30 +306,30 @@ func TestDashboardIndex_PrefixSearch(t *testing.T) { func TestDashboardIndex_MultipleTokensInRow(t *testing.T) { t.Run("multiple-tokens-beginning", func(t *testing.T) { - _, reader, _ := initTestIndexFromDashes(t, testPrefixDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), reader, testAllowAllFilter, + index := initTestOrgIndexFromDashes(t, testPrefixDashboards) + checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, DashboardQuery{Query: "Archer da"}, ) }) t.Run("multiple-tokens-beginning-lower", func(t *testing.T) { - _, reader, _ := initTestIndexFromDashes(t, testPrefixDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), reader, testAllowAllFilter, + index := initTestOrgIndexFromDashes(t, testPrefixDashboards) + checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, DashboardQuery{Query: "da archer"}, ) }) // Not sure it is great this matches, but t.Run("multiple-tokens-middle", func(t *testing.T) { - _, reader, _ := initTestIndexFromDashes(t, testPrefixDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), reader, testAllowAllFilter, + index := initTestOrgIndexFromDashes(t, testPrefixDashboards) + checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, DashboardQuery{Query: "ar Da"}, ) }) t.Run("multiple-tokens-middle-lower", func(t *testing.T) { - _, reader, _ := initTestIndexFromDashes(t, testPrefixDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), reader, testAllowAllFilter, + index := initTestOrgIndexFromDashes(t, testPrefixDashboards) + checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, DashboardQuery{Query: "doc sy"}, ) }) @@ -335,8 +347,8 @@ var longPrefixDashboards = []dashboard{ func TestDashboardIndex_PrefixNgramExceeded(t *testing.T) { t.Run("prefix-search-ngram-exceeded", func(t *testing.T) { - _, reader, _ := initTestIndexFromDashes(t, longPrefixDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), reader, testAllowAllFilter, + index := initTestOrgIndexFromDashes(t, longPrefixDashboards) + checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, DashboardQuery{Query: "Eyjafjallajöku"}, ) }) @@ -361,14 +373,14 @@ var scatteredTokensDashboards = []dashboard{ func TestDashboardIndex_MultipleTokensScattered(t *testing.T) { t.Run("scattered-tokens-match", func(t *testing.T) { - _, reader, _ := initTestIndexFromDashes(t, scatteredTokensDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), reader, testAllowAllFilter, + index := initTestOrgIndexFromDashes(t, scatteredTokensDashboards) + checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, DashboardQuery{Query: "dead secret"}, ) }) t.Run("scattered-tokens-match-reversed", func(t *testing.T) { - _, reader, _ := initTestIndexFromDashes(t, scatteredTokensDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), reader, testAllowAllFilter, + index := initTestOrgIndexFromDashes(t, scatteredTokensDashboards) + checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, DashboardQuery{Query: "powerful secret"}, ) }) @@ -432,15 +444,15 @@ var dashboardsWithFolders = []dashboard{ func TestDashboardIndex_Folders(t *testing.T) { t.Run("folders-indexed", func(t *testing.T) { - _, reader, _ := initTestIndexFromDashes(t, dashboardsWithFolders) - checkSearchResponse(t, filepath.Base(t.Name()), reader, testAllowAllFilter, + index := initTestOrgIndexFromDashes(t, dashboardsWithFolders) + checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, DashboardQuery{Query: "My folder", Kind: []string{string(entityKindFolder)}}, ) }) t.Run("folders-dashboard-has-folder", func(t *testing.T) { - _, reader, _ := initTestIndexFromDashes(t, dashboardsWithFolders) + index := initTestOrgIndexFromDashes(t, dashboardsWithFolders) // TODO: golden file compare does not work here. - resp := doSearchQuery(context.Background(), testLogger, reader, testAllowAllFilter, + resp := doSearchQuery(context.Background(), testLogger, index, testAllowAllFilter, DashboardQuery{Query: "Dashboard in folder", Kind: []string{string(entityKindDashboard)}}, &NoopQueryExtender{}, "") custom, ok := resp.Frames[0].Meta.Custom.(*customMeta) @@ -449,19 +461,23 @@ func TestDashboardIndex_Folders(t *testing.T) { require.Equal(t, "/dashboards/f/1/", custom.Locations["1"].URL) }) t.Run("folders-dashboard-removed-on-folder-removed", func(t *testing.T) { - index, reader, writer := initTestIndexFromDashes(t, dashboardsWithFolders) - newReader, err := index.removeFolder(context.Background(), writer, reader, "1") + index := initTestIndexFromDashes(t, dashboardsWithFolders) + orgIdx, ok := index.getOrgIndex(testOrgID) + require.True(t, ok) + err := index.removeFolder(context.Background(), orgIdx, "1") require.NoError(t, err) // In response we expect one dashboard which does not belong to removed folder. - checkSearchResponse(t, filepath.Base(t.Name()), newReader, testAllowAllFilter, + checkSearchResponse(t, filepath.Base(t.Name()), orgIdx, testAllowAllFilter, DashboardQuery{Query: "dash", Kind: []string{string(entityKindDashboard)}}, ) }) t.Run("folders-panels-removed-on-folder-removed", func(t *testing.T) { - index, reader, writer := initTestIndexFromDashes(t, dashboardsWithFolders) - newReader, err := index.removeFolder(context.Background(), writer, reader, "1") + index := initTestIndexFromDashes(t, dashboardsWithFolders) + orgIdx, ok := index.getOrgIndex(testOrgID) + require.True(t, ok) + err := index.removeFolder(context.Background(), orgIdx, "1") require.NoError(t, err) - resp := doSearchQuery(context.Background(), testLogger, newReader, testAllowAllFilter, + resp := doSearchQuery(context.Background(), testLogger, orgIdx, testAllowAllFilter, DashboardQuery{Query: "Panel", Kind: []string{string(entityKindPanel)}}, &NoopQueryExtender{}, "") custom, ok := resp.Frames[0].Meta.Custom.(*customMeta) @@ -492,10 +508,10 @@ var dashboardsWithPanels = []dashboard{ func TestDashboardIndex_Panels(t *testing.T) { t.Run("panels-indexed", func(t *testing.T) { - _, reader, _ := initTestIndexFromDashes(t, dashboardsWithPanels) + index := initTestOrgIndexFromDashes(t, dashboardsWithPanels) // TODO: golden file compare does not work here. resp := doSearchQuery( - context.Background(), testLogger, reader, testAllowAllFilter, + context.Background(), testLogger, index, testAllowAllFilter, DashboardQuery{Query: "Panel", Kind: []string{string(entityKindPanel)}}, &NoopQueryExtender{}, "") custom, ok := resp.Frames[0].Meta.Custom.(*customMeta) @@ -504,10 +520,12 @@ func TestDashboardIndex_Panels(t *testing.T) { require.Equal(t, "/d/1/", custom.Locations["1"].URL) }) t.Run("panels-panel-removed-on-dashboard-removed", func(t *testing.T) { - index, reader, writer := initTestIndexFromDashes(t, dashboardsWithPanels) - newReader, err := index.removeDashboard(context.Background(), writer, reader, "1") + index := initTestIndexFromDashes(t, dashboardsWithPanels) + orgIdx, ok := index.getOrgIndex(testOrgID) + require.True(t, ok) + err := index.removeDashboard(context.Background(), orgIdx, "1") require.NoError(t, err) - checkSearchResponse(t, filepath.Base(t.Name()), newReader, testAllowAllFilter, + checkSearchResponse(t, filepath.Base(t.Name()), orgIdx, testAllowAllFilter, DashboardQuery{Query: "Panel", Kind: []string{string(entityKindPanel)}}, ) }) @@ -532,15 +550,15 @@ var punctuationSplitNgramDashboards = []dashboard{ func TestDashboardIndex_PunctuationNgram(t *testing.T) { t.Run("ngram-punctuation-split", func(t *testing.T) { - _, reader, _ := initTestIndexFromDashes(t, punctuationSplitNgramDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), reader, testAllowAllFilter, + index := initTestOrgIndexFromDashes(t, punctuationSplitNgramDashboards) + checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, DashboardQuery{Query: "tork he"}, ) }) t.Run("ngram-simple", func(t *testing.T) { - _, reader, _ := initTestIndexFromDashes(t, punctuationSplitNgramDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), reader, testAllowAllFilter, + index := initTestOrgIndexFromDashes(t, punctuationSplitNgramDashboards) + checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, DashboardQuery{Query: "hea"}, ) }) @@ -558,8 +576,8 @@ var camelCaseNgramDashboards = []dashboard{ func TestDashboardIndex_CamelCaseNgram(t *testing.T) { t.Run("ngram-camel-case-split", func(t *testing.T) { - _, reader, _ := initTestIndexFromDashes(t, camelCaseNgramDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), reader, testAllowAllFilter, + index := initTestOrgIndexFromDashes(t, camelCaseNgramDashboards) + checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, DashboardQuery{Query: "tork"}, ) }) diff --git a/pkg/services/searchV2/service.go b/pkg/services/searchV2/service.go index bfcf080a044..2bd11f15b60 100644 --- a/pkg/services/searchV2/service.go +++ b/pkg/services/searchV2/service.go @@ -26,7 +26,7 @@ type StandardSearchService struct { ac accesscontrol.AccessControl logger log.Logger - dashboardIndex *dashboardIndex + dashboardIndex *searchIndex extender DashboardIndexExtender reIndexCh chan struct{} } @@ -41,7 +41,7 @@ func ProvideService(cfg *setting.Cfg, sql *sqlstore.SQLStore, entityEventStore s sql: sql, ac: ac, }, - dashboardIndex: newDashboardIndex( + dashboardIndex: newSearchIndex( newSQLDashboardLoader(sql), entityEventStore, extender.GetDocumentExtender(), @@ -163,7 +163,7 @@ func (s *StandardSearchService) DoDashboardQuery(ctx context.Context, user *back return rsp } - reader, err := s.dashboardIndex.getOrCreateReader(ctx, orgID) + index, err := s.dashboardIndex.getOrCreateOrgIndex(ctx, orgID) if err != nil { rsp.Error = err return rsp @@ -175,5 +175,5 @@ func (s *StandardSearchService) DoDashboardQuery(ctx context.Context, user *back return rsp } - return doSearchQuery(ctx, s.logger, reader, filter, q, s.extender.GetQueryExtender(q), s.cfg.AppSubURL) + return doSearchQuery(ctx, s.logger, index, filter, q, s.extender.GetQueryExtender(q), s.cfg.AppSubURL) }