diff --git a/head.go b/head.go index 087e64d1b..b14c056f1 100644 --- a/head.go +++ b/head.go @@ -576,6 +576,12 @@ func (h *Head) Truncate(mint int64) (err error) { if err != nil { return errors.Wrap(err, "get segment range") } + // Start a new segment, so low ingestion volume TSDB don't have more WAL than + // needed. + err = h.wal.NextSegment() + if err != nil { + return errors.Wrap(err, "next segment") + } last-- // Never consider last segment for checkpoint. if last < 0 { return nil // no segments yet. diff --git a/head_test.go b/head_test.go index 8f5774bfc..dbe6fecd5 100644 --- a/head_test.go +++ b/head_test.go @@ -1128,3 +1128,40 @@ func TestWalRepair(t *testing.T) { } } + +func TestNewWalSegmentOnTruncate(t *testing.T) { + dir, err := ioutil.TempDir("", "test_wal_segemnts") + testutil.Ok(t, err) + defer func() { + testutil.Ok(t, os.RemoveAll(dir)) + }() + wlog, err := wal.NewSize(nil, nil, dir, 32768) + testutil.Ok(t, err) + + h, err := NewHead(nil, nil, wlog, 1000) + testutil.Ok(t, err) + defer h.Close() + add := func(ts int64) { + app := h.Appender() + _, err := app.Add(labels.Labels{{"a", "b"}}, ts, 0) + testutil.Ok(t, err) + testutil.Ok(t, app.Commit()) + } + + add(0) + _, last, err := wlog.Segments() + testutil.Ok(t, err) + testutil.Equals(t, 0, last) + + add(1) + testutil.Ok(t, h.Truncate(1)) + _, last, err = wlog.Segments() + testutil.Ok(t, err) + testutil.Equals(t, 1, last) + + add(2) + testutil.Ok(t, h.Truncate(2)) + _, last, err = wlog.Segments() + testutil.Ok(t, err) + testutil.Equals(t, 2, last) +} diff --git a/wal/wal.go b/wal/wal.go index cb2e11ff9..f0e413f5c 100644 --- a/wal/wal.go +++ b/wal/wal.go @@ -393,6 +393,13 @@ func SegmentName(dir string, i int) string { return filepath.Join(dir, fmt.Sprintf("%08d", i)) } +// NextSegment creates the next segment and closes the previous one. +func (w *WAL) NextSegment() error { + w.mtx.Lock() + defer w.mtx.Unlock() + return w.nextSegment() +} + // nextSegment creates the next segment and closes the previous one. func (w *WAL) nextSegment() error { // Only flush the current page if it actually holds data.