Fix noinlineerr findings: internal/snapshot (refs #61)

This commit is contained in:
2026-08-07 16:59:56 +00:00
parent 26cbb63749
commit 68cffba35d
6 changed files with 69 additions and 32 deletions

View File

@@ -479,7 +479,8 @@ func (b *BackupEngine) Backup(ctx context.Context, fsys fs.FS, root string) (str
dummyData := []byte(chunkHash)
// Upload to S3 as a blob
if err := b.s3Client.PutBlob(ctx, blobHash, dummyData); err != nil {
err = b.s3Client.PutBlob(ctx, blobHash, dummyData)
if err != nil {
return "", err
}

View File

@@ -35,7 +35,9 @@ func DecodeManifest(r io.Reader) (*Manifest, error) {
// Decode JSON manifest
var manifest Manifest
if err := json.NewDecoder(zr).Decode(&manifest); err != nil {
err = json.NewDecoder(zr).Decode(&manifest)
if err != nil {
return nil, fmt.Errorf("decoding manifest: %w", err)
}
@@ -58,13 +60,15 @@ func EncodeManifest(manifest *Manifest, compressionLevel int) ([]byte, error) {
return nil, fmt.Errorf("creating zstd writer: %w", err)
}
if _, err := writer.Write(jsonData); err != nil {
_, err = writer.Write(jsonData)
if err != nil {
_ = writer.Close()
return nil, fmt.Errorf("writing compressed data: %w", err)
}
if err := writer.Close(); err != nil {
err = writer.Close()
if err != nil {
return nil, fmt.Errorf("closing zstd writer: %w", err)
}

View File

@@ -213,7 +213,8 @@ func (s *Scanner) Scan(ctx context.Context, path string, snapshotID string) (*Sc
filesToProcess := scanResult.FilesToProcess
// Phase 1b: Detect deleted files by comparing DB against scanned files
if err := s.detectDeletedFilesFromMap(ctx, knownFiles, existingFiles, result); err != nil {
err = s.detectDeletedFilesFromMap(ctx, knownFiles, existingFiles, result)
if err != nil {
return nil, fmt.Errorf("detecting deleted files: %w", err)
}
@@ -264,7 +265,8 @@ func (s *Scanner) loadDatabaseState(ctx context.Context, path string) (map[strin
s.ui.Begin("Loading known chunks from local index database.")
if err := s.loadKnownChunks(ctx); err != nil {
err = s.loadKnownChunks(ctx)
if err != nil {
return nil, fmt.Errorf("loading known chunks: %w", err)
}
@@ -1262,7 +1264,8 @@ func (s *Scanner) handleBlobReady(blobWithReader *blob.BlobWithReader) error {
return fmt.Errorf("uploading blob %s: %w", finishedBlob.Hash, err)
}
if err := s.recordBlobMetadata(ctx, finishedBlob, blobExists, startTime); err != nil {
err = s.recordBlobMetadata(ctx, finishedBlob, blobExists, startTime)
if err != nil {
s.cleanupBlobTempFile(blobWithReader)
return err
@@ -1274,7 +1277,8 @@ func (s *Scanner) handleBlobReady(blobWithReader *blob.BlobWithReader) error {
s.removePendingChunkHashes(blobWithReader.InsertedChunkHashes)
// Flush files whose chunks are now all committed
if err := s.flushCompletedPendingFiles(ctx); err != nil {
err = s.flushCompletedPendingFiles(ctx)
if err != nil {
return fmt.Errorf("flushing completed files: %w", err)
}
@@ -1287,7 +1291,9 @@ func (s *Scanner) uploadBlobIfNeeded(ctx context.Context, blobPath string, blobW
// Check if blob already exists (deduplication after restart)
destination := s.storage.Info().Location
if _, err := s.storage.Stat(ctx, blobPath); err == nil {
_, err := s.storage.Stat(ctx, blobPath)
if err == nil {
log.Info("Blob already exists in storage, skipping upload",
"hash", finishedBlob.Hash, "size", humanize.Bytes(uint64(finishedBlob.Compressed)))
s.ui.Info("Blob %s (%s) already exists at %s. Skipping upload.",
@@ -1301,7 +1307,7 @@ func (s *Scanner) uploadBlobIfNeeded(ctx context.Context, blobPath string, blobW
progressCallback := s.makeUploadProgressCallback(ctx, finishedBlob, startTime)
err := s.storage.PutWithProgress(ctx, blobPath, blobWithReader.Reader, finishedBlob.Compressed, progressCallback)
err = s.storage.PutWithProgress(ctx, blobPath, blobWithReader.Reader, finishedBlob.Compressed, progressCallback)
if err != nil {
log.Error("Failed to upload blob", "hash", finishedBlob.Hash, "error", err)

View File

@@ -185,11 +185,13 @@ func TestScannerLargeFile(t *testing.T) {
largeContent[i] = byte((i * 7919) ^ (i >> 3))
}
if err := fs.MkdirAll("/source", 0755); err != nil {
err := fs.MkdirAll("/source", 0755)
if err != nil {
t.Fatal(err)
}
if err := afero.WriteFile(fs, "/source/large.bin", largeContent, 0644); err != nil {
err = afero.WriteFile(fs, "/source/large.bin", largeContent, 0644)
if err != nil {
t.Fatal(err)
}

View File

@@ -258,7 +258,8 @@ func (sm *SnapshotManager) ExportSnapshotMetadata(ctx context.Context, dbPath st
}
// Step 7: Upload to S3 in snapshot subdirectory
if err := sm.uploadSnapshotArtifacts(ctx, snapshotID, finalData, blobManifest); err != nil {
err = sm.uploadSnapshotArtifacts(ctx, snapshotID, finalData, blobManifest)
if err != nil {
return err
}
@@ -278,7 +279,8 @@ func (sm *SnapshotManager) prepareExportDB(ctx context.Context, dbPath, snapshot
tempDBPath := filepath.Join(tempDir, "snapshot.db")
log.Debug("Copying database to temporary location", "source", dbPath, "destination", tempDBPath)
if err := sm.copyFile(dbPath, tempDBPath); err != nil {
err := sm.copyFile(dbPath, tempDBPath)
if err != nil {
return nil, "", fmt.Errorf("copying database: %w", err)
}
@@ -304,7 +306,8 @@ func (sm *SnapshotManager) prepareExportDB(ctx context.Context, dbPath, snapshot
// Step 3: VACUUM the database to remove deleted data and compact
// This is critical for security - ensures no stale/deleted data is uploaded
if err := sm.vacuumDatabase(tempDBPath); err != nil {
err = sm.vacuumDatabase(tempDBPath)
if err != nil {
return nil, "", fmt.Errorf("vacuuming database: %w", err)
}
@@ -312,7 +315,9 @@ func (sm *SnapshotManager) prepareExportDB(ctx context.Context, dbPath, snapshot
// Step 4: Compress and encrypt the binary database file
compressedPath := filepath.Join(tempDir, "db.zst.age")
if err := sm.compressFile(tempDBPath, compressedPath); err != nil {
err = sm.compressFile(tempDBPath, compressedPath)
if err != nil {
return nil, "", fmt.Errorf("compressing database: %w", err)
}
@@ -423,38 +428,46 @@ func (sm *SnapshotManager) cleanSnapshotDB(ctx context.Context, dbPath string, s
}()
// Execute cleanup steps in order
if err := sm.deleteOtherSnapshots(ctx, tx, snapshotID); err != nil {
err = sm.deleteOtherSnapshots(ctx, tx, snapshotID)
if err != nil {
return nil, fmt.Errorf("step 1 - delete other snapshots: %w", err)
}
if err := sm.deleteOrphanedSnapshotAssociations(ctx, tx, snapshotID); err != nil {
err = sm.deleteOrphanedSnapshotAssociations(ctx, tx, snapshotID)
if err != nil {
return nil, fmt.Errorf("step 2 - delete orphaned snapshot associations: %w", err)
}
if err := sm.deleteOrphanedFiles(ctx, tx, snapshotID); err != nil {
err = sm.deleteOrphanedFiles(ctx, tx, snapshotID)
if err != nil {
return nil, fmt.Errorf("step 3 - delete orphaned files: %w", err)
}
if err := sm.deleteOrphanedChunkToFileMappings(ctx, tx); err != nil {
err = sm.deleteOrphanedChunkToFileMappings(ctx, tx)
if err != nil {
return nil, fmt.Errorf("step 4 - delete orphaned chunk-to-file mappings: %w", err)
}
if err := sm.deleteOrphanedBlobs(ctx, tx, snapshotID); err != nil {
err = sm.deleteOrphanedBlobs(ctx, tx, snapshotID)
if err != nil {
return nil, fmt.Errorf("step 5 - delete orphaned blobs: %w", err)
}
if err := sm.deleteOrphanedBlobToChunkMappings(ctx, tx); err != nil {
err = sm.deleteOrphanedBlobToChunkMappings(ctx, tx)
if err != nil {
return nil, fmt.Errorf("step 6 - delete orphaned blob-to-chunk mappings: %w", err)
}
if err := sm.deleteOrphanedChunks(ctx, tx); err != nil {
err = sm.deleteOrphanedChunks(ctx, tx)
if err != nil {
return nil, fmt.Errorf("step 7 - delete orphaned chunks: %w", err)
}
// Commit transaction
log.Debug("[Temp DB Cleanup] Committing cleanup transaction")
if err := tx.Commit(); err != nil {
err = tx.Commit()
if err != nil {
return nil, fmt.Errorf("committing transaction: %w", err)
}
@@ -509,7 +522,8 @@ func (sm *SnapshotManager) vacuumDatabase(dbPath string) error {
log.Debug("Running VACUUM on database", "path", dbPath)
cmd := exec.Command("sqlite3", dbPath, "VACUUM;")
if output, err := cmd.CombinedOutput(); err != nil {
output, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("running VACUUM: %w (output: %s)", err, string(output))
}
@@ -559,12 +573,14 @@ func (sm *SnapshotManager) compressFile(inputPath, outputPath string) error {
}
}()
if _, err := io.Copy(writer, input); err != nil {
_, err = io.Copy(writer, input)
if err != nil {
return fmt.Errorf("compressing data: %w", err)
}
// Close writer to flush all data
if err := writer.Close(); err != nil {
err = writer.Close()
if err != nil {
return fmt.Errorf("closing writer: %w", err)
}

View File

@@ -85,13 +85,16 @@ func TestCleanSnapshotDBEmptySnapshot(t *testing.T) {
}
// Close the database
if err := db.Close(); err != nil {
err = db.Close()
if err != nil {
t.Fatalf("failed to close database: %v", err)
}
// Copy database
tempDBPath := filepath.Join(tempDir, "temp.db")
if err := copyFile(fs, dbPath, tempDBPath); err != nil {
err = copyFile(fs, dbPath, tempDBPath)
if err != nil {
t.Fatalf("failed to copy database: %v", err)
}
@@ -105,7 +108,9 @@ func TestCleanSnapshotDBEmptySnapshot(t *testing.T) {
config: cfg,
fs: fs,
}
if _, err := sm.cleanSnapshotDB(ctx, tempDBPath, snapshot.ID.String()); err != nil {
_, err = sm.cleanSnapshotDB(ctx, tempDBPath, snapshot.ID.String())
if err != nil {
t.Fatalf("failed to clean snapshot database: %v", err)
}
@@ -171,13 +176,16 @@ func TestCleanSnapshotDBNonExistentSnapshot(t *testing.T) {
}
// Close immediately
if err := db.Close(); err != nil {
err = db.Close()
if err != nil {
t.Fatalf("failed to close database: %v", err)
}
// Copy database
tempDBPath := filepath.Join(tempDir, "temp.db")
if err := copyFile(fs, dbPath, tempDBPath); err != nil {
err = copyFile(fs, dbPath, tempDBPath)
if err != nil {
t.Fatalf("failed to copy database: %v", err)
}