Handle every error return flagged by golangci-lint's errcheck rather than discarding it: - run.go: add a cleanup() helper that logs a warning (and ignores ErrNotExist) when removing a temp file fails, so leaked scratch files are surfaced; use it for all best-effort removals. - copy.go / extract.go: log a warning on deferred Close() failures for the source file, destination DB, and result-set rows. - extract.go: on the rollback path, ignore the benign sql.ErrTxDone (already committed) and log any other rollback failure. - verify.go: add killCat() which ignores os.ErrProcessDone (zstdcat already exited via SIGPIPE) and logs any unexpected kill failure. make check is clean (0 lint issues, tests pass).
This commit is contained in:
+19
-10
@@ -9,6 +9,15 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// cleanup removes a temporary file, logging a warning if removal fails so
|
||||
// that leaked scratch files are surfaced rather than silently ignored. A
|
||||
// missing file is not an error.
|
||||
func cleanup(path string) {
|
||||
if err := os.Remove(path); err != nil && !os.IsNotExist(err) {
|
||||
slog.Warn("failed to remove temporary file", "path", path, "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func Run(targetDates []time.Time) error {
|
||||
snapshotDir, snapshotDate, err := FindLatestDailySnapshot()
|
||||
if err != nil {
|
||||
@@ -100,7 +109,7 @@ func Run(targetDates []time.Time) error {
|
||||
if err := ExtractDay(dstDB, extractedDB, targetDay); err != nil {
|
||||
if errors.Is(err, ErrNoPosts) {
|
||||
slog.Warn("no posts found, skipping day", "date", dayStr)
|
||||
os.Remove(extractedDB)
|
||||
cleanup(extractedDB)
|
||||
skipped++
|
||||
continue
|
||||
}
|
||||
@@ -109,7 +118,7 @@ func Run(targetDates []time.Time) error {
|
||||
|
||||
// Dump to SQL and compress
|
||||
if err := os.MkdirAll(outputDir, 0755); err != nil {
|
||||
os.Remove(extractedDB)
|
||||
cleanup(extractedDB)
|
||||
return fmt.Errorf("creating output directory %s: %w", outputDir, err)
|
||||
}
|
||||
|
||||
@@ -117,35 +126,35 @@ func Run(targetDates []time.Time) error {
|
||||
|
||||
slog.Info("dumping and compressing", "tmp_output", outputTmp)
|
||||
if err := DumpAndCompress(extractedDB, outputTmp); err != nil {
|
||||
os.Remove(outputTmp)
|
||||
os.Remove(extractedDB)
|
||||
cleanup(outputTmp)
|
||||
cleanup(extractedDB)
|
||||
return fmt.Errorf("dump and compress for %s: %w", dayStr, err)
|
||||
}
|
||||
|
||||
slog.Info("verifying compressed output")
|
||||
if err := VerifyOutput(outputTmp); err != nil {
|
||||
os.Remove(outputTmp)
|
||||
os.Remove(extractedDB)
|
||||
cleanup(outputTmp)
|
||||
cleanup(extractedDB)
|
||||
return fmt.Errorf("verification failed for %s: %w", dayStr, err)
|
||||
}
|
||||
|
||||
// Atomic rename to final path
|
||||
slog.Info("renaming to final output", "from", outputTmp, "to", outputFinal)
|
||||
if err := os.Rename(outputTmp, outputFinal); err != nil {
|
||||
os.Remove(outputTmp)
|
||||
os.Remove(extractedDB)
|
||||
cleanup(outputTmp)
|
||||
cleanup(extractedDB)
|
||||
return fmt.Errorf("atomic rename for %s: %w", dayStr, err)
|
||||
}
|
||||
|
||||
info, err := os.Stat(outputFinal)
|
||||
if err != nil {
|
||||
os.Remove(extractedDB)
|
||||
cleanup(extractedDB)
|
||||
return fmt.Errorf("stat final output: %w", err)
|
||||
}
|
||||
slog.Info("day completed", "date", dayStr, "path", outputFinal, "size_bytes", info.Size())
|
||||
|
||||
// Remove extracted DB to reclaim space immediately
|
||||
os.Remove(extractedDB)
|
||||
cleanup(extractedDB)
|
||||
processed++
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user