@@ -365,14 +365,37 @@ func (p *Planner) computeTasks(
365
365
return nil , nil , fmt .Errorf ("failed to delete outdated metas during planning: %w" , err )
366
366
}
367
367
368
+ // Resolve TSDBs
369
+ tsdbs , err := p .tsdbStore .ResolveTSDBs (ctx , table , tenant )
370
+ if err != nil {
371
+ level .Error (logger ).Log ("msg" , "failed to resolve tsdbs" , "err" , err )
372
+ return nil , nil , fmt .Errorf ("failed to resolve tsdbs: %w" , err )
373
+ }
374
+
375
+ if len (tsdbs ) == 0 {
376
+ return nil , metas , nil
377
+ }
378
+
379
+ openTSDBs , err := openAllTSDBs (ctx , table , tenant , p .tsdbStore , tsdbs )
380
+ if err != nil {
381
+ return nil , nil , fmt .Errorf ("failed to open all tsdbs: %w" , err )
382
+ }
383
+ defer func () {
384
+ for idx , reader := range openTSDBs {
385
+ if err := reader .Close (); err != nil {
386
+ level .Error (logger ).Log ("msg" , "failed to close index" , "err" , err , "tsdb" , idx .Name ())
387
+ }
388
+ }
389
+ }()
390
+
368
391
for _ , ownershipRange := range ownershipRanges {
369
392
logger := log .With (logger , "ownership" , ownershipRange .String ())
370
393
371
394
// Filter only the metas that overlap in the ownership range
372
395
metasInBounds := bloomshipper .FilterMetasOverlappingBounds (metas , ownershipRange )
373
396
374
397
// Find gaps in the TSDBs for this tenant/table
375
- gaps , err := p .findOutdatedGaps (ctx , tenant , table , ownershipRange , metasInBounds , logger )
398
+ gaps , err := p .findOutdatedGaps (ctx , tenant , openTSDBs , ownershipRange , metasInBounds , logger )
376
399
if err != nil {
377
400
level .Error (logger ).Log ("msg" , "failed to find outdated gaps" , "err" , err )
378
401
continue
@@ -453,6 +476,26 @@ func (p *Planner) processTenantTaskResults(
453
476
return tasksSucceed , nil
454
477
}
455
478
479
+ func openAllTSDBs (
480
+ ctx context.Context ,
481
+ table config.DayTable ,
482
+ tenant string ,
483
+ store common.TSDBStore ,
484
+ tsdbs []tsdb.SingleTenantTSDBIdentifier ,
485
+ ) (map [tsdb.SingleTenantTSDBIdentifier ]common.ClosableForSeries , error ) {
486
+ openTSDBs := make (map [tsdb.SingleTenantTSDBIdentifier ]common.ClosableForSeries , len (tsdbs ))
487
+ for _ , idx := range tsdbs {
488
+ tsdb , err := store .LoadTSDB (ctx , table , tenant , idx )
489
+ if err != nil {
490
+ return nil , fmt .Errorf ("failed to load tsdb: %w" , err )
491
+ }
492
+
493
+ openTSDBs [idx ] = tsdb
494
+ }
495
+
496
+ return openTSDBs , nil
497
+ }
498
+
456
499
// deleteOutdatedMetasAndBlocks filters out the outdated metas from the `metas` argument and deletes them from the store.
457
500
// It returns the up-to-date metas from the `metas` argument.
458
501
func (p * Planner ) deleteOutdatedMetasAndBlocks (
@@ -655,28 +698,17 @@ func (p *Planner) tenants(ctx context.Context, table config.DayTable) (*iter.Sli
655
698
// This is a performance optimization to avoid expensive re-reindexing
656
699
type blockPlan struct {
657
700
tsdb tsdb.SingleTenantTSDBIdentifier
658
- gaps []protos.GapWithBlocks
701
+ gaps []protos.Gap
659
702
}
660
703
661
704
func (p * Planner ) findOutdatedGaps (
662
705
ctx context.Context ,
663
706
tenant string ,
664
- table config. DayTable ,
707
+ tsdbs map [tsdb. SingleTenantTSDBIdentifier ]common. ClosableForSeries ,
665
708
ownershipRange v1.FingerprintBounds ,
666
709
metas []bloomshipper.Meta ,
667
710
logger log.Logger ,
668
711
) ([]blockPlan , error ) {
669
- // Resolve TSDBs
670
- tsdbs , err := p .tsdbStore .ResolveTSDBs (ctx , table , tenant )
671
- if err != nil {
672
- level .Error (logger ).Log ("msg" , "failed to resolve tsdbs" , "err" , err )
673
- return nil , fmt .Errorf ("failed to resolve tsdbs: %w" , err )
674
- }
675
-
676
- if len (tsdbs ) == 0 {
677
- return nil , nil
678
- }
679
-
680
712
// Determine which TSDBs have gaps in the ownership range and need to
681
713
// be processed.
682
714
tsdbsWithGaps , err := gapsBetweenTSDBsAndMetas (ownershipRange , tsdbs , metas )
@@ -690,7 +722,7 @@ func (p *Planner) findOutdatedGaps(
690
722
return nil , nil
691
723
}
692
724
693
- work , err := blockPlansForGaps (tsdbsWithGaps , metas )
725
+ work , err := blockPlansForGaps (ctx , tenant , tsdbsWithGaps , metas )
694
726
if err != nil {
695
727
level .Error (logger ).Log ("msg" , "failed to create plan" , "err" , err )
696
728
return nil , fmt .Errorf ("failed to create plan: %w" , err )
@@ -701,18 +733,19 @@ func (p *Planner) findOutdatedGaps(
701
733
702
734
// Used to signal the gaps that need to be populated for a tsdb
703
735
type tsdbGaps struct {
704
- tsdb tsdb.SingleTenantTSDBIdentifier
705
- gaps []v1.FingerprintBounds
736
+ tsdbIdentifier tsdb.SingleTenantTSDBIdentifier
737
+ tsdb common.ClosableForSeries
738
+ gaps []v1.FingerprintBounds
706
739
}
707
740
708
741
// gapsBetweenTSDBsAndMetas returns if the metas are up-to-date with the TSDBs. This is determined by asserting
709
742
// that for each TSDB, there are metas covering the entire ownership range which were generated from that specific TSDB.
710
743
func gapsBetweenTSDBsAndMetas (
711
744
ownershipRange v1.FingerprintBounds ,
712
- tsdbs [] tsdb.SingleTenantTSDBIdentifier ,
745
+ tsdbs map [ tsdb.SingleTenantTSDBIdentifier ]common. ClosableForSeries ,
713
746
metas []bloomshipper.Meta ,
714
747
) (res []tsdbGaps , err error ) {
715
- for _ , db := range tsdbs {
748
+ for db , tsdb := range tsdbs {
716
749
id := db .Name ()
717
750
718
751
relevantMetas := make ([]v1.FingerprintBounds , 0 , len (metas ))
@@ -731,8 +764,9 @@ func gapsBetweenTSDBsAndMetas(
731
764
732
765
if len (gaps ) > 0 {
733
766
res = append (res , tsdbGaps {
734
- tsdb : db ,
735
- gaps : gaps ,
767
+ tsdbIdentifier : db ,
768
+ tsdb : tsdb ,
769
+ gaps : gaps ,
736
770
})
737
771
}
738
772
}
@@ -743,22 +777,35 @@ func gapsBetweenTSDBsAndMetas(
743
777
// blockPlansForGaps groups tsdb gaps we wish to fill with overlapping but out of date blocks.
744
778
// This allows us to expedite bloom generation by using existing blocks to fill in the gaps
745
779
// since many will contain the same chunks.
746
- func blockPlansForGaps (tsdbs []tsdbGaps , metas []bloomshipper.Meta ) ([]blockPlan , error ) {
780
+ func blockPlansForGaps (
781
+ ctx context.Context ,
782
+ tenant string ,
783
+ tsdbs []tsdbGaps ,
784
+ metas []bloomshipper.Meta ,
785
+ ) ([]blockPlan , error ) {
747
786
plans := make ([]blockPlan , 0 , len (tsdbs ))
748
787
749
788
for _ , idx := range tsdbs {
750
789
plan := blockPlan {
751
- tsdb : idx .tsdb ,
752
- gaps : make ([]protos.GapWithBlocks , 0 , len (idx .gaps )),
790
+ tsdb : idx .tsdbIdentifier ,
791
+ gaps : make ([]protos.Gap , 0 , len (idx .gaps )),
753
792
}
754
793
755
794
for _ , gap := range idx .gaps {
756
- planGap := protos.GapWithBlocks {
795
+ planGap := protos.Gap {
757
796
Bounds : gap ,
758
797
}
759
798
760
- for _ , meta := range metas {
799
+ seriesItr , err := common .NewTSDBSeriesIter (ctx , tenant , idx .tsdb , gap )
800
+ if err != nil {
801
+ return nil , fmt .Errorf ("failed to load series from TSDB for gap (%s): %w" , gap .String (), err )
802
+ }
803
+ planGap .Series , err = iter .Collect (seriesItr )
804
+ if err != nil {
805
+ return nil , fmt .Errorf ("failed to collect series: %w" , err )
806
+ }
761
807
808
+ for _ , meta := range metas {
762
809
if meta .Bounds .Intersection (gap ) == nil {
763
810
// this meta doesn't overlap the gap, skip
764
811
continue
0 commit comments