fix: publish database backups atomically#9756
Conversation
Keep incomplete gzip output hidden until backup generation succeeds and surface valid empty archives through health warnings. Co-Authored-By: Paperclip <noreply@paperclip.ing> Co-authored-by: Cursor <cursoragent@cursor.com>
|
✅ All checks passing — ready for Greptile review and maintainer approval. — commitperclip |
Greptile SummaryThis PR fixes two related backup reliability gaps: incomplete archives could be observed at the final path during a failed write, and a valid gzip with zero uncompressed bytes passed health checks without any specific signal.
Confidence Score: 5/5Safe to merge — the atomic rename pattern is correct, both temp paths are in the same directory as the destination ensuring POSIX rename atomicity, cleanup is properly guarded by existsSync, and the empty-gzip detector cannot false-positive on normal backups. The core change is a well-scoped staged-rename pattern with no changes to final filenames, retention matching, or restore format. The ISIZE trailer check is implemented correctly, the gunzipSync short-circuit via maxOutputLength prevents decompressing large files, and both new behaviors are covered by dedicated regression tests. No files require special attention. Important Files Changed
Reviews (2): Last reviewed commit: "fix: preserve concurrent backup failures" | Re-trigger Greptile |
|
CTO review: changes requested before approval.
The atomic same-directory staging/rename behavior and dedicated empty-gzip warning otherwise match the requested blast-radius constraints. The second Greptile note (double read for the rare ISIZE-zero path) is non-blocking. |
Retain both compression and pg_dump diagnostics when they fail together so operators can act on every underlying cause. Co-Authored-By: Paperclip <noreply@paperclip.ing> Co-authored-by: Cursor <cursoragent@cursor.com>
|
CTO re-review approved at ee65c56. The concurrent-failure path now preserves both causes with AggregateError; policy, Greptile, build, typecheck, server/workspace tests, serialized suites, canary, and security checks pass. Focused backup/health verification is 19/19. GitHub does not allow this authenticated PR author to submit a formal approval. The remaining e2e job is still running and remains a merge gate; do not merge until it passes. |
|
All required CI is now complete and green at @cryppadotta, please perform the upstream maintainer merge review. The authenticated PR author cannot merge, enable auto-merge, request a formal review, or submit a self-approval. |
Thinking Path
Linked Issues or Issue Description
What happened?
Interrupted
pg_dumpor JavaScript compression can expose a partial final archive; a valid empty gzip is not identified as unusable.Expected behavior
Final backup filenames appear only after successful compression and process exit, temporary output is removed on handled failures, and empty valid gzip archives produce a dedicated warning.
Steps to reproduce
Start a backup with a dump producer that writes partial stdout and exits non-zero, then inspect the backup directory; separately place
gzipSync(\"\")at the newest.sql.gzpath and query health.Paperclip version or commit
masterat5d42382d.Deployment mode
All modes using logical database backups.
What Changed
pg_dumpand JavaScript backup engines in unique files beside the destination, then rename after successful completion.pg_dumpchild and compression pipeline to settle and clean staged output on failure without deleting an existing final archive.database_backup_empty, including redacted health output.pg_dumppublication and valid empty-gzip health classification.Verification
pnpm exec vitest run packages/db/src/backup-lib.test.ts server/src/__tests__/health.test.tsRisks
Model Used
Checklist
Fixes: #/Closes #/Refs #OR (b) described the issue in-PR following the relevant issue template#NNN/github.com/paperclipai/paperclipURLs)docs/...,fix/...) and contains no internal Paperclip ticket id or instance-derived detailsMade with Cursor