Skip to content

Commit beddbff

Browse files
authored
Validate block range periods config in the compactor (#3534)
Signed-off-by: Marco Pracucci <[email protected]>
1 parent f25bd3f commit beddbff

File tree

4 files changed

+58
-1
lines changed

4 files changed

+58
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
* [ENHANCEMENT] /metrics now supports OpenMetrics output. HTTP and gRPC servers metrics can now include exemplars. #3524
2727
* [ENHANCEMENT] Expose gRPC keepalive policy options by gRPC server. #3524
2828
* [ENHANCEMENT] Blocks storage: enabled caching of `meta.json` attributes, configurable via `-blocks-storage.bucket-store.metadata-cache.metafile-attributes-ttl`. #3528
29+
* [ENHANCEMENT] Compactor: added a config validation check to fail fast if the compactor has been configured invalid block range periods (each period is expected to be a multiple of the previous one). #3534
2930
* [BUGFIX] Blocks storage ingester: fixed some cases leading to a TSDB WAL corruption after a partial write to disk. #3423
3031
* [BUGFIX] Blocks storage: Fix the race between ingestion and `/flush` call resulting in overlapping blocks. #3422
3132
* [BUGFIX] Querier: fixed `-querier.max-query-into-future` which wasn't correctly enforced on range queries. #3452

pkg/compactor/compactor.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ import (
2929
"github.com/cortexproject/cortex/pkg/util/services"
3030
)
3131

32+
var (
33+
errInvalidBlockRanges = "compactor block range periods should be divisible by the previous one, but %s is not divisible by %s"
34+
)
35+
3236
// Config holds the Compactor config.
3337
type Config struct {
3438
BlockRanges cortex_tsdb.DurationList `yaml:"block_ranges"`
@@ -83,6 +87,17 @@ func (cfg *Config) RegisterFlags(f *flag.FlagSet) {
8387
f.Var(&cfg.DisabledTenants, "compactor.disabled-tenants", "Comma separated list of tenants that cannot be compacted by this compactor. If specified, and compactor would normally pick given tenant for compaction (via -compactor.enabled-tenants or sharding), it will be ignored instead.")
8488
}
8589

90+
func (cfg *Config) Validate() error {
91+
// Each block range period should be divisible by the previous one.
92+
for i := 1; i < len(cfg.BlockRanges); i++ {
93+
if cfg.BlockRanges[i]%cfg.BlockRanges[i-1] != 0 {
94+
return errors.Errorf(errInvalidBlockRanges, cfg.BlockRanges[i].String(), cfg.BlockRanges[i-1].String())
95+
}
96+
}
97+
98+
return nil
99+
}
100+
86101
// Compactor is a multi-tenant TSDB blocks compactor based on Thanos.
87102
type Compactor struct {
88103
services.Service

pkg/compactor/compactor_test.go

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package compactor
33
import (
44
"context"
55
"encoding/json"
6-
"errors"
76
"flag"
87
"fmt"
98
"io/ioutil"
@@ -17,6 +16,7 @@ import (
1716

1817
"github.com/go-kit/kit/log"
1918
"github.com/oklog/ulid"
19+
"github.com/pkg/errors"
2020
"github.com/prometheus/client_golang/prometheus"
2121
prom_testutil "github.com/prometheus/client_golang/prometheus/testutil"
2222
"github.com/prometheus/prometheus/pkg/labels"
@@ -80,6 +80,44 @@ func TestConfig_ShouldSupportCliFlags(t *testing.T) {
8080
assert.Equal(t, 123, cfg.CompactionRetries)
8181
}
8282

83+
func TestConfig_Validate(t *testing.T) {
84+
tests := map[string]struct {
85+
setup func(cfg *Config)
86+
expected string
87+
}{
88+
"should pass with the default config": {
89+
setup: func(cfg *Config) {},
90+
expected: "",
91+
},
92+
"should pass with only 1 block range period": {
93+
setup: func(cfg *Config) {
94+
cfg.BlockRanges = cortex_tsdb.DurationList{time.Hour}
95+
},
96+
expected: "",
97+
},
98+
"should fail with non divisible block range periods": {
99+
setup: func(cfg *Config) {
100+
cfg.BlockRanges = cortex_tsdb.DurationList{2 * time.Hour, 12 * time.Hour, 24 * time.Hour, 30 * time.Hour}
101+
},
102+
expected: errors.Errorf(errInvalidBlockRanges, 30*time.Hour, 24*time.Hour).Error(),
103+
},
104+
}
105+
106+
for testName, testData := range tests {
107+
t.Run(testName, func(t *testing.T) {
108+
cfg := &Config{}
109+
flagext.DefaultValues(cfg)
110+
testData.setup(cfg)
111+
112+
if actualErr := cfg.Validate(); testData.expected != "" {
113+
assert.EqualError(t, actualErr, testData.expected)
114+
} else {
115+
assert.NoError(t, actualErr)
116+
}
117+
})
118+
}
119+
}
120+
83121
func TestCompactor_ShouldDoNothingOnNoUserBlocks(t *testing.T) {
84122
t.Parallel()
85123

pkg/cortex/cortex.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,9 @@ func (c *Config) Validate(log log.Logger) error {
208208
if err := c.StoreGateway.Validate(c.LimitsConfig); err != nil {
209209
return errors.Wrap(err, "invalid store-gateway config")
210210
}
211+
if err := c.Compactor.Validate(); err != nil {
212+
return errors.Wrap(err, "invalid compactor config")
213+
}
211214

212215
if c.Storage.Engine == storage.StorageEngineBlocks && c.Querier.SecondStoreEngine != storage.StorageEngineChunks && len(c.Schema.Configs) > 0 {
213216
level.Warn(log).Log("schema configuration is not used by the blocks storage engine, and will have no effect")

0 commit comments

Comments
 (0)