update storage-api to only build index if it owns the namespace (#108418)

* update storage-api to only build index if it owns the namespace

---------

Co-authored-by: Mustafa Sencer Özcan <mustafasencer.ozcan@grafana.com>
This commit is contained in:
Will Assis
2025-07-23 15:59:24 -04:00
committed by GitHub
co-authored by Mustafa Sencer Özcan
parent 4df4f9cc07
commit 981fdb29d4
6 changed files with 73 additions and 16 deletions
+40 -1
View File
@@ -4,6 +4,7 @@ import (
"cmp"
"context"
"fmt"
"hash/fnv"
"log/slog"
"slices"
"strings"
@@ -19,6 +20,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
"github.com/grafana/authlib/types"
"github.com/grafana/dskit/ring"
dashboardv1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1beta1"
folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
@@ -109,6 +111,9 @@ type searchSupport struct {
initMinSize int
initMaxSize int
ring *ring.Ring
ringLifecycler *ring.BasicLifecycler
buildIndex singleflight.Group
// Index queue processors
@@ -128,7 +133,7 @@ var (
_ resourcepb.ManagedObjectIndexServer = (*searchSupport)(nil)
)
func newSearchSupport(opts SearchOptions, storage StorageBackend, access types.AccessClient, blob BlobSupport, tracer trace.Tracer, indexMetrics *BleveIndexMetrics) (support *searchSupport, err error) {
func newSearchSupport(opts SearchOptions, storage StorageBackend, access types.AccessClient, blob BlobSupport, tracer trace.Tracer, indexMetrics *BleveIndexMetrics, ring *ring.Ring, ringLifecycler *ring.BasicLifecycler) (support *searchSupport, err error) {
// No backend search support
if opts.Backend == nil {
return nil, nil
@@ -155,6 +160,8 @@ func newSearchSupport(opts SearchOptions, storage StorageBackend, access types.A
indexEventsChan: make(chan *IndexEvent),
indexQueueProcessors: make(map[string]*indexQueueProcessor),
rebuildInterval: opts.RebuildInterval,
ring: ring,
ringLifecycler: ringLifecycler,
}
info, err := opts.Resources.GetDocumentBuilders()
@@ -379,6 +386,33 @@ func (s *searchSupport) GetStats(ctx context.Context, req *resourcepb.ResourceSt
return rsp, nil
}
func (s *searchSupport) shouldBuildIndex(info ResourceStats) bool {
if s.ring == nil {
s.log.Debug("ring is not setup. Will proceed to build index")
return true
}
if s.ringLifecycler == nil {
s.log.Error("missing ring lifecycler")
return true
}
ringHasher := fnv.New32a()
_, err := ringHasher.Write([]byte(info.Namespace))
if err != nil {
s.log.Error("error hashing namespace", "namespace", info.Namespace, "err", err)
return true
}
rs, err := s.ring.GetWithOptions(ringHasher.Sum32(), searchOwnerRead, ring.WithReplicationFactor(s.ring.ReplicationFactor()))
if err != nil {
s.log.Error("error getting replicaset from ring", "namespace", info.Namespace, "err", err)
return true
}
return rs.Includes(s.ringLifecycler.GetInstanceAddr())
}
func (s *searchSupport) buildIndexes(ctx context.Context, rebuild bool) (int, error) {
totalBatchesIndexed := 0
group := errgroup.Group{}
@@ -395,6 +429,11 @@ func (s *searchSupport) buildIndexes(ctx context.Context, rebuild bool) (int, er
continue
}
if !s.shouldBuildIndex(info) {
s.log.Debug("skip building index", "namespace", info.Namespace, "group", info.Group, "resource", info.Resource)
continue
}
group.Go(func() error {
if rebuild {
// we need to clear the cache to make sure we get the latest usage insights data