From e51a17b50159d397544d7f62775ee9ceaf48cfc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20=C5=A0tibran=C3=BD?= Date: Wed, 5 Jan 2022 10:40:00 +0100 Subject: [PATCH] CompactBlockMetas should produce correct mint/maxt for overlapping blocks. (#10108) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Peter Štibraný --- tsdb/compact.go | 15 ++++++++------- tsdb/compact_test.go | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/tsdb/compact.go b/tsdb/compact.go index 7c12d1729..1d7e93f7f 100644 --- a/tsdb/compact.go +++ b/tsdb/compact.go @@ -18,7 +18,6 @@ import ( "crypto/rand" "fmt" "io" - "math" "os" "path/filepath" "sort" @@ -347,19 +346,20 @@ func splitByRange(ds []dirMeta, tr int64) [][]dirMeta { } // CompactBlockMetas merges many block metas into one, combining it's source blocks together -// and adjusting compaction level. +// and adjusting compaction level. Min/Max time of result block meta covers all input blocks. func CompactBlockMetas(uid ulid.ULID, blocks ...*BlockMeta) *BlockMeta { res := &BlockMeta{ - ULID: uid, - MinTime: blocks[0].MinTime, + ULID: uid, } sources := map[ulid.ULID]struct{}{} - // For overlapping blocks, the Maxt can be - // in any block so we track it globally. - maxt := int64(math.MinInt64) + mint := blocks[0].MinTime + maxt := blocks[0].MaxTime for _, b := range blocks { + if b.MinTime < mint { + mint = b.MinTime + } if b.MaxTime > maxt { maxt = b.MaxTime } @@ -384,6 +384,7 @@ func CompactBlockMetas(uid ulid.ULID, blocks ...*BlockMeta) *BlockMeta { return res.Compaction.Sources[i].Compare(res.Compaction.Sources[j]) < 0 }) + res.MinTime = mint res.MaxTime = maxt return res } diff --git a/tsdb/compact_test.go b/tsdb/compact_test.go index bac9bfdfe..dc8ffc85f 100644 --- a/tsdb/compact_test.go +++ b/tsdb/compact_test.go @@ -25,6 +25,7 @@ import ( "time" "github.com/go-kit/log" + "github.com/oklog/ulid" "github.com/pkg/errors" prom_testutil "github.com/prometheus/client_golang/prometheus/testutil" "github.com/stretchr/testify/require" @@ -1311,3 +1312,38 @@ func TestDeleteCompactionBlockAfterFailedReload(t *testing.T) { }) } } + +func TestCompactBlockMetas(t *testing.T) { + parent1 := ulid.MustNew(100, nil) + parent2 := ulid.MustNew(200, nil) + parent3 := ulid.MustNew(300, nil) + parent4 := ulid.MustNew(400, nil) + + input := []*BlockMeta{ + {ULID: parent1, MinTime: 1000, MaxTime: 2000, Compaction: BlockMetaCompaction{Level: 2, Sources: []ulid.ULID{ulid.MustNew(1, nil), ulid.MustNew(10, nil)}}}, + {ULID: parent2, MinTime: 200, MaxTime: 500, Compaction: BlockMetaCompaction{Level: 1}}, + {ULID: parent3, MinTime: 500, MaxTime: 2500, Compaction: BlockMetaCompaction{Level: 3, Sources: []ulid.ULID{ulid.MustNew(5, nil), ulid.MustNew(6, nil)}}}, + {ULID: parent4, MinTime: 100, MaxTime: 900, Compaction: BlockMetaCompaction{Level: 1}}, + } + + outUlid := ulid.MustNew(1000, nil) + output := CompactBlockMetas(outUlid, input...) + + expected := &BlockMeta{ + ULID: outUlid, + MinTime: 100, + MaxTime: 2500, + Stats: BlockStats{}, + Compaction: BlockMetaCompaction{ + Level: 4, + Sources: []ulid.ULID{ulid.MustNew(1, nil), ulid.MustNew(5, nil), ulid.MustNew(6, nil), ulid.MustNew(10, nil)}, + Parents: []BlockDesc{ + {ULID: parent1, MinTime: 1000, MaxTime: 2000}, + {ULID: parent2, MinTime: 200, MaxTime: 500}, + {ULID: parent3, MinTime: 500, MaxTime: 2500}, + {ULID: parent4, MinTime: 100, MaxTime: 900}, + }, + }, + } + require.Equal(t, expected, output) +}