diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ed9ee86e4..0d8de39943 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ We use *breaking :warning:* to mark changes that are not backward compatible (re - [#6172](https://github.com/thanos-io/thanos/pull/6172) query-frontend: return JSON formatted errors for invalid PromQL expression in the split by interval middleware. - [#6171](https://github.com/thanos-io/thanos/pull/6171) Store: fix error handling on limits. +- [#6183](https://github.com/thanos-io/thanos/pull/6183) Receiver: fix off by one in multitsdb flush that will result in empty blocks if the head only contains one sample ### Changed - [#6168](https://github.com/thanos-io/thanos/pull/6168) Receiver: Make ketama hashring fail early when configured with number of nodes lower than the replication factor. diff --git a/pkg/receive/multitsdb.go b/pkg/receive/multitsdb.go index 28b82d1dcf..d7f77c9efb 100644 --- a/pkg/receive/multitsdb.go +++ b/pkg/receive/multitsdb.go @@ -235,7 +235,7 @@ func (t *MultiTSDB) Flush() error { wg.Add(1) go func() { head := db.Head() - if err := db.CompactHead(tsdb.NewRangeHead(head, head.MinTime(), head.MaxTime()-1)); err != nil { + if err := db.CompactHead(tsdb.NewRangeHead(head, head.MinTime(), head.MaxTime())); err != nil { errmtx.Lock() merr.Add(err) errmtx.Unlock() diff --git a/pkg/receive/multitsdb_test.go b/pkg/receive/multitsdb_test.go index 83cb35323b..40dc176493 100644 --- a/pkg/receive/multitsdb_test.go +++ b/pkg/receive/multitsdb_test.go @@ -162,6 +162,35 @@ func TestMultiTSDB(t *testing.T) { testMulitTSDBSeries(t, m) }) + + t.Run("flush with one sample produces a block", func(t *testing.T) { + const testTenant = "test_tenant" + m := NewMultiTSDB( + dir, logger, prometheus.NewRegistry(), &tsdb.Options{ + MinBlockDuration: (2 * time.Hour).Milliseconds(), + MaxBlockDuration: (2 * time.Hour).Milliseconds(), + RetentionDuration: (6 * time.Hour).Milliseconds(), + NoLockfile: true, + }, + labels.FromStrings("replica", "01"), + "tenant_id", + nil, + false, + metadata.NoneFunc, + ) + defer func() { testutil.Ok(t, m.Close()) }() + + testutil.Ok(t, m.Flush()) + testutil.Ok(t, m.Open()) + testutil.Ok(t, appendSample(m, testTenant, time.Now())) + + tenant := m.tenants[testTenant] + db := tenant.readyStorage().Get() + + testutil.Equals(t, 0, len(db.Blocks())) + testutil.Ok(t, m.Flush()) + testutil.Equals(t, 1, len(db.Blocks())) + }) } var (