Label the index cleanup totals as totals (closes #306)
check / check (push) Waiting to run

The summary printed by the local index cleanup before each backup gave,
in brackets after each removed count, the number of snapshots, files,
chunks or blobs left in the local index, worded "(N remain)", which
read as incomplete or orphaned rows left over: removing the only
incomplete snapshot printed "1 removed (1 remain)". Each line now
labels that figure as the total of its kind left in the local index.

Model: opus-5-5
This commit was merged in pull request #379.
This commit is contained in:
2026-10-14 02:03:51 +02:00
parent 66ea7f5f45
commit 5db2e920e5
2 changed files with 68 additions and 4 deletions
+60
View File
@@ -1,13 +1,17 @@
package vaultik //nolint:testpackage // exercises unexported count helpers package vaultik //nolint:testpackage // exercises unexported count helpers
import ( import (
"bytes"
"context" "context"
"testing" "testing"
"time"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"sneak.berlin/go/vaultik/internal/database" "sneak.berlin/go/vaultik/internal/database"
"sneak.berlin/go/vaultik/internal/log" "sneak.berlin/go/vaultik/internal/log"
"sneak.berlin/go/vaultik/internal/snapshot"
"sneak.berlin/go/vaultik/internal/ui"
) )
// TestTableCountForReportSurfacesReadFailure is the regression guard for // TestTableCountForReportSurfacesReadFailure is the regression guard for
@@ -76,3 +80,59 @@ func TestCountDiffUnknownWhenEitherSideUnknown(t *testing.T) {
assert.Nil(t, countDiff(&before, nil), "unknown after yields unknown delta") assert.Nil(t, countDiff(&before, nil), "unknown after yields unknown delta")
assert.Nil(t, countDiff(nil, nil)) assert.Nil(t, countDiff(nil, nil))
} }
// TestPruneDatabaseSummaryLabelsTotals removes the only incomplete
// snapshot from an index that also holds a complete one. The figure in
// brackets is every snapshot left in the local index, so the line must
// say so rather than read as incomplete snapshots that remain.
func TestPruneDatabaseSummaryLabelsTotals(t *testing.T) {
log.Initialize(log.Config{})
t.Parallel()
ctx := context.Background()
db, err := database.New(ctx, ":memory:")
require.NoError(t, err)
t.Cleanup(func() { _ = db.Close() })
repos := database.NewRepositories(db)
startedAt := time.Date(2026, 1, 2, 3, 4, 5, 0, time.UTC)
completedAt := startedAt.Add(time.Minute)
require.NoError(t, repos.Snapshots.Create(ctx, nil, &database.Snapshot{
ID: "host_complete_2026-01-02T03:04:05Z",
Hostname: "host",
StartedAt: startedAt,
CompletedAt: &completedAt,
}))
require.NoError(t, repos.Snapshots.Create(ctx, nil, &database.Snapshot{
ID: "host_incomplete_2026-01-02T03:04:05Z",
Hostname: "host",
StartedAt: startedAt,
}))
var out bytes.Buffer
v := &Vaultik{
DB: db,
Repositories: repos,
SnapshotManager: snapshot.NewSnapshotManager(
snapshot.SnapshotManagerParams{Repos: repos}),
UI: ui.NewWithColor(&out, false),
}
v.SetContext(ctx)
result, err := v.PruneDatabase()
require.NoError(t, err)
require.Equal(t, int64(1), result.SnapshotsDeleted)
assert.Contains(t, out.String(), "Incomplete snapshots: 1 removed "+
"(total snapshots left in the local index: 1).")
assert.Contains(t, out.String(), "Orphaned files: 0 removed "+
"(total files left in the local index: 0).")
assert.Contains(t, out.String(), "Orphaned chunks: 0 removed "+
"(total chunks left in the local index: 0).")
assert.Contains(t, out.String(), "Orphaned blobs: 0 removed "+
"(total blobs left in the local index: 0).")
}
+8 -4
View File
@@ -1902,13 +1902,17 @@ func (v *Vaultik) PruneDatabase() (*PruneResult, error) {
snapshotsRemain := countDiff(snapshotCountBefore, &result.SnapshotsDeleted) snapshotsRemain := countDiff(snapshotCountBefore, &result.SnapshotsDeleted)
v.UI.Completef("Pruned local index database.") v.UI.Completef("Pruned local index database.")
v.UI.Detailf("Incomplete snapshots: %s removed (%s remain).", v.UI.Detailf("Incomplete snapshots: %s removed "+
"(total snapshots left in the local index: %s).",
countText(&result.SnapshotsDeleted), countText(snapshotsRemain)) countText(&result.SnapshotsDeleted), countText(snapshotsRemain))
v.UI.Detailf("Orphaned files: %s removed (%s remain).", v.UI.Detailf("Orphaned files: %s removed "+
"(total files left in the local index: %s).",
countText(result.FilesDeleted), countText(fileCountAfter)) countText(result.FilesDeleted), countText(fileCountAfter))
v.UI.Detailf("Orphaned chunks: %s removed (%s remain).", v.UI.Detailf("Orphaned chunks: %s removed "+
"(total chunks left in the local index: %s).",
countText(result.ChunksDeleted), countText(chunkCountAfter)) countText(result.ChunksDeleted), countText(chunkCountAfter))
v.UI.Detailf("Orphaned blobs: %s removed (%s remain).", v.UI.Detailf("Orphaned blobs: %s removed "+
"(total blobs left in the local index: %s).",
countText(result.BlobsDeleted), countText(blobCountAfter)) countText(result.BlobsDeleted), countText(blobCountAfter))
return result, nil return result, nil