Count each file, byte and upload once in backup statistics (closes #225)
check / check (push) Waiting to run
check / check (push) Waiting to run
The scanner added a changed file's bytes again for each new chunk and counted a file as unchanged for each chunk already stored. It now counts files and bytes once, in the scan phase, and counts its own uploads, so a --cron run, which has no progress reporter, records them. The blob count no longer adds earlier paths' blobs again. The snapshots row now stores the size of all files in total_size and the referenced blobs' sizes in blob_size, blob_uncompressed_size and compression_ratio, as docs/DATAMODEL.md says. Those sizes come from one query, and a failed query fails the snapshot. DATAMODEL.md now says chunk_count and blob_count count what the run added. Removed UpdateSnapshotStats and GetCountBySnapshot, which nothing calls any more. Model: opus-5-5
This commit is contained in:
@@ -145,6 +145,65 @@ func TestSnapshotRepositoryUpdateCounts(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// GetSnapshotBlobSizes totals the blobs the snapshot references, and only
|
||||
// those.
|
||||
func TestSnapshotRepositoryGetSnapshotBlobSizes(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
db, cleanup := setupTestDB(t)
|
||||
defer cleanup()
|
||||
|
||||
ctx := context.Background()
|
||||
repos := database.NewRepositories(db)
|
||||
|
||||
snapshot := &database.Snapshot{
|
||||
ID: "2024-01-03T12:00:00Z",
|
||||
Hostname: testHostname,
|
||||
VaultikVersion: testVersion,
|
||||
StartedAt: time.Now().Truncate(time.Second),
|
||||
}
|
||||
|
||||
err := repos.Snapshots.Create(ctx, nil, snapshot)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create snapshot: %v", err)
|
||||
}
|
||||
|
||||
blobs := []*database.Blob{
|
||||
{Hash: "referenced-1", CompressedSize: 10, UncompressedSize: 100},
|
||||
{Hash: "referenced-2", CompressedSize: 20, UncompressedSize: 200},
|
||||
{Hash: "unreferenced", CompressedSize: 40, UncompressedSize: 400},
|
||||
}
|
||||
|
||||
for _, blob := range blobs {
|
||||
blob.ID = types.NewBlobID()
|
||||
blob.CreatedTS = time.Now().Truncate(time.Second)
|
||||
|
||||
err = repos.Blobs.Create(ctx, nil, blob)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create blob %s: %v", blob.Hash, err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, blob := range blobs[:2] {
|
||||
err = repos.Snapshots.AddBlob(ctx, nil, snapshot.ID.String(),
|
||||
blob.ID, blob.Hash)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to add blob %s to snapshot: %v", blob.Hash, err)
|
||||
}
|
||||
}
|
||||
|
||||
compressed, uncompressed, err := repos.Snapshots.GetSnapshotBlobSizes(
|
||||
ctx, snapshot.ID.String())
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get snapshot blob sizes: %v", err)
|
||||
}
|
||||
|
||||
if compressed != 30 || uncompressed != 300 {
|
||||
t.Errorf("blob sizes: got %d and %d, want 30 and 300",
|
||||
compressed, uncompressed)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSnapshotRepositoryListRecent(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user