@ -70,7 +70,7 @@ func (s *SimpleBloomController) compactTenant(
tenant string ,
ownershipRange v1 . FingerprintBounds ,
) error {
logger := log . With ( s . logger , "ownership" , ownershipRange , "o rg_id" , tenant , "table" , table . Addr ( ) )
logger := log . With ( s . logger , "org_id" , tenant , "table" , table . Addr ( ) , "ownership" , ownershipRange . String ( ) )
client , err := s . bloomStore . Client ( table . ModelTime ( ) )
if err != nil {
@ -92,6 +92,15 @@ func (s *SimpleBloomController) compactTenant(
return errors . Wrap ( err , "failed to get metas" )
}
level . Debug ( logger ) . Log ( "msg" , "found relevant metas" , "metas" , len ( metas ) )
// fetch all metas overlapping our ownership range so we can safely
// check which metas can be deleted even if they only partially overlap out ownership range
superset , err := s . fetchSuperSet ( ctx , tenant , table , ownershipRange , metas , logger )
if err != nil {
return errors . Wrap ( err , "failed to fetch superset" )
}
// build compaction plans
work , err := s . findOutdatedGaps ( ctx , tenant , table , ownershipRange , metas , logger )
if err != nil {
@ -104,6 +113,63 @@ func (s *SimpleBloomController) compactTenant(
return errors . Wrap ( err , "failed to build gaps" )
}
// combine built and superset metas
// in preparation for removing outdated ones
combined := append ( superset , built ... )
outdated := outdatedMetas ( combined )
level . Debug ( logger ) . Log ( "msg" , "found outdated metas" , "outdated" , len ( outdated ) )
var (
deletedMetas int
deletedBlocks int
)
defer func ( ) {
s . metrics . metasDeleted . Add ( float64 ( deletedMetas ) )
s . metrics . blocksDeleted . Add ( float64 ( deletedBlocks ) )
} ( )
for _ , meta := range outdated {
for _ , block := range meta . Blocks {
err := client . DeleteBlocks ( ctx , [ ] bloomshipper . BlockRef { block } )
if err != nil {
if client . IsObjectNotFoundErr ( err ) {
level . Debug ( logger ) . Log ( "msg" , "block not found while attempting delete, continuing" , "block" , block . String ( ) )
} else {
level . Error ( logger ) . Log ( "msg" , "failed to delete block" , "err" , err , "block" , block . String ( ) )
return errors . Wrap ( err , "failed to delete block" )
}
}
deletedBlocks ++
level . Debug ( logger ) . Log ( "msg" , "removed outdated block" , "block" , block . String ( ) )
}
err = client . DeleteMetas ( ctx , [ ] bloomshipper . MetaRef { meta . MetaRef } )
if err != nil {
if client . IsObjectNotFoundErr ( err ) {
level . Debug ( logger ) . Log ( "msg" , "meta not found while attempting delete, continuing" , "meta" , meta . MetaRef . String ( ) )
} else {
level . Error ( logger ) . Log ( "msg" , "failed to delete meta" , "err" , err , "meta" , meta . MetaRef . String ( ) )
return errors . Wrap ( err , "failed to delete meta" )
}
}
deletedMetas ++
level . Debug ( logger ) . Log ( "msg" , "removed outdated meta" , "meta" , meta . MetaRef . String ( ) )
}
level . Debug ( logger ) . Log ( "msg" , "finished compaction" )
return nil
}
// fetchSuperSet fetches all metas which overlap the ownership range of the first set of metas we've resolved
func ( s * SimpleBloomController ) fetchSuperSet (
ctx context . Context ,
tenant string ,
table config . DayTable ,
ownershipRange v1 . FingerprintBounds ,
metas [ ] bloomshipper . Meta ,
logger log . Logger ,
) ( [ ] bloomshipper . Meta , error ) {
// in order to delete outdates metas which only partially fall within the ownership range,
// we need to fetcha all metas in the entire bound range of the first set of metas we've resolved
/ *
@ -121,12 +187,28 @@ func (s *SimpleBloomController) compactTenant(
union := superset . Union ( meta . Bounds )
if len ( union ) > 1 {
level . Error ( logger ) . Log ( "msg" , "meta bounds union is not a single range" , "union" , union )
return errors . New ( "meta bounds union is not a single range" )
return nil , errors . New ( "meta bounds union is not a single range" )
}
superset = union [ 0 ]
}
metas , err = s . bloomStore . FetchMetas (
within := superset . Within ( ownershipRange )
level . Debug ( logger ) . Log (
"msg" , "looking for superset metas" ,
"superset" , superset . String ( ) ,
"superset_within" , within ,
)
if within {
// we don't need to fetch any more metas
// NB(owen-d): here we copy metas into the output. This is slightly inefficient, but
// helps prevent mutability bugs by returning the same slice as the input.
results := make ( [ ] bloomshipper . Meta , len ( metas ) )
copy ( results , metas )
return results , nil
}
supersetMetas , err := s . bloomStore . FetchMetas (
ctx ,
bloomshipper . MetaSearchParams {
TenantID : tenant ,
@ -134,42 +216,20 @@ func (s *SimpleBloomController) compactTenant(
Keyspace : superset ,
} ,
)
if err != nil {
level . Error ( logger ) . Log ( "msg" , "failed to get meta superset range" , "err" , err , "superset" , superset )
return errors . Wrap ( err , "failed to get meta supseret range" )
return nil , errors . Wrap ( err , "failed to get meta supseret range" )
}
// combine built and pre-existing metas
// in preparation for removing outdated metas
metas = append ( metas , built ... )
outdated := outdatedMetas ( metas )
for _ , meta := range outdated {
for _ , block := range meta . Blocks {
if err := client . DeleteBlocks ( ctx , [ ] bloomshipper . BlockRef { block } ) ; err != nil {
if client . IsObjectNotFoundErr ( err ) {
level . Debug ( logger ) . Log ( "msg" , "block not found while attempting delete, continuing" , "block" , block )
continue
}
level . Error ( logger ) . Log ( "msg" , "failed to delete blocks" , "err" , err )
return errors . Wrap ( err , "failed to delete blocks" )
}
}
if err := client . DeleteMetas ( ctx , [ ] bloomshipper . MetaRef { meta . MetaRef } ) ; err != nil {
if client . IsObjectNotFoundErr ( err ) {
level . Debug ( logger ) . Log ( "msg" , "meta not found while attempting delete, continuing" , "meta" , meta . MetaRef )
} else {
level . Error ( logger ) . Log ( "msg" , "failed to delete metas" , "err" , err )
return errors . Wrap ( err , "failed to delete metas" )
}
}
}
level . Debug ( logger ) . Log ( "msg" , "finished compaction" )
return nil
level . Debug ( logger ) . Log (
"msg" , "found superset metas" ,
"metas" , len ( metas ) ,
"fresh_metas" , len ( supersetMetas ) ,
"delta" , len ( supersetMetas ) - len ( metas ) ,
)
return supersetMetas , nil
}
func ( s * SimpleBloomController ) findOutdatedGaps (
@ -271,6 +331,7 @@ func (s *SimpleBloomController) buildGaps(
for i := range plan . gaps {
gap := plan . gaps [ i ]
logger := log . With ( logger , "gap" , gap . bounds . String ( ) , "tsdb" , plan . tsdb . Name ( ) )
meta := bloomshipper . Meta {
MetaRef : bloomshipper . MetaRef {
@ -304,9 +365,11 @@ func (s *SimpleBloomController) buildGaps(
blocksIter ,
s . rwFn ,
s . metrics ,
log . With ( log ger, "tsdb" , plan . tsdb . Name ( ) , "ownership" , gap ) ,
logger ,
)
level . Debug ( logger ) . Log ( "msg" , "generating blocks" , "overlapping_blocks" , len ( gap . blocks ) )
newBlocks := gen . Generate ( ctx )
if err != nil {
level . Error ( logger ) . Log ( "msg" , "failed to generate bloom" , "err" , err )
@ -333,6 +396,16 @@ func (s *SimpleBloomController) buildGaps(
blocksIter . Close ( )
return nil , errors . Wrap ( err , "failed to write block" )
}
s . metrics . blocksCreated . Inc ( )
totalGapKeyspace := ( gap . bounds . Max - gap . bounds . Min )
progress := ( built . Bounds . Max - gap . bounds . Min )
pct := float64 ( progress ) / float64 ( totalGapKeyspace ) * 100
level . Debug ( logger ) . Log (
"msg" , "uploaded block" ,
"block" , built . BlockRef . String ( ) ,
"progress_pct" , fmt . Sprintf ( "%.2f" , pct ) ,
)
meta . Blocks = append ( meta . Blocks , built . BlockRef )
}
@ -346,6 +419,7 @@ func (s *SimpleBloomController) buildGaps(
blocksIter . Close ( )
// Write the new meta
// TODO(owen-d): put total size in log, total time in metrics+log
ref , err := bloomshipper . MetaRefFrom ( tenant , table . Addr ( ) , gap . bounds , meta . Sources , meta . Blocks )
if err != nil {
level . Error ( logger ) . Log ( "msg" , "failed to checksum meta" , "err" , err )
@ -357,8 +431,10 @@ func (s *SimpleBloomController) buildGaps(
level . Error ( logger ) . Log ( "msg" , "failed to write meta" , "err" , err )
return nil , errors . Wrap ( err , "failed to write meta" )
}
created = append ( created , meta )
s . metrics . metasCreated . Inc ( )
level . Debug ( logger ) . Log ( "msg" , "uploaded meta" , "meta" , meta . MetaRef . String ( ) )
created = append ( created , meta )
totalSeries += uint64 ( seriesItrWithCounter . Count ( ) )
}
}