FIXED:
- internal/restore/engine.go: Already fixed (previous commit)
- internal/drill/engine.go: Decompress on host with pgzip BEFORE copying to container
- Added decompressWithPgzip() helper function
- Removed 3x gunzip -c calls from executeRestore()
CANNOT FIX (PostgreSQL limitation):
- internal/pitr/recovery_config.go: restore_command is a shell command
that PostgreSQL itself runs to fetch WAL files. Cannot use Go here.
VERIFIED: No external gzip/gunzip/pigz processes will appear in htop
during backup or restore operations (except PITR which is PostgreSQL-controlled).
- restorePostgreSQLSQL: Now uses pgzip.NewReader → psql stdin
- restoreMySQLSQL: Now uses pgzip.NewReader → mysql stdin
- executeRestoreWithDecompression: Now uses pgzip instead of gunzip/pigz shell
- Added executeRestoreWithPgzipStream for SQL format restores
No more gzip/gunzip processes visible in htop during cluster restore.
Uses klauspost/pgzip for parallel decompression (multi-core).
- New internal/tui/health.go (644 lines)
- 10 health checks with async execution
- Added to Tools menu as 'System Health Check'
- Color-coded results + recommendations
- Updated CHANGELOG.md for v4.2.0
Keep TUI and CLI in sync - Quick Win integration
- Show estimated uncompressed size (3x compression ratio)
- Display estimated RTO based on current profile
- Calculation: extract time + restore time
- Uses profile settings (jobs count affects speed)
- Simple display, detailed analysis in CLI
TUI shows essentials, CLI has full 'restore preview' command
for detailed analysis before restore.
Quick Win #1 - See what you'll get before restoring
- Shows file info, format, size estimates
- Calculates estimated restore time (RTO)
- Displays table count and largest tables
- Validates backup integrity
- Provides resource recommendations
- No restore needed - reads metadata only
Usage:
dbbackup restore preview mydb.dump.gz
dbbackup restore preview cluster_backup.tar.gz --estimate
Shipped in 1 day as promised.
- Added --socket flag for explicit socket path
- Auto-detect socket from --host if path starts with /
- Updated mysqldump/mysql commands to use -S flag
- Works for both backup and restore operations
- Added dbbackup_build_info{server,version,commit} metric for fleet tracking
- Fixed docs: pitr_base is auto-assigned by 'dbbackup pitr base', not CLI flag value
- Updated EXPORTER.md and METRICS.md with build_info documentation
- Add backup_type label (full/incremental/pitr_base) to core metrics
- Add new dbbackup_backup_by_type metric for backup type distribution
- Add complete PITR metrics: pitr_enabled, pitr_archive_lag_seconds,
pitr_chain_valid, pitr_gap_count, pitr_recovery_window_minutes
- Add PITR-specific alerting rules for archive lag and chain integrity
- Update METRICS.md and EXPORTER.md documentation
- Bump version to 4.1.0
- Auto-detect hostname for --server flag instead of defaulting to 'default'
- Add --catalog-db flag to metrics serve/export commands
- Add dbbackup_rpo_seconds metric to dedup metrics for unified alerting
- Improve catalog sync to detect and warn about legacy backups without metadata
- Update EXPORTER.md documentation with new flags and troubleshooting
🎉 Version 4.0.0 - Stable Release
Major Features Now Fully Working:
- Incremental backups (--backup-type incremental --base-backup <path>)
- Notification system (SMTP + webhook via environment variables)
- Full enterprise deployment examples (Ansible, K8s, Terraform)
This release represents feature-complete, production-ready state.
Breaking Changes from v3.x:
- CLI flags synced with documentation
- Notify package now active (reads NOTIFY_* env vars)
Tested:
- All unit tests pass
- go vet clean
- Cross-platform builds successful
Replace non-existent --notify CLI flag with correct environment
variable approach for email notifications. The notification system
uses NOTIFY_SMTP_* environment variables, not a CLI flag.
BREAKING CHANGE: The --instance flag is renamed to --server to avoid
collision with Prometheus's reserved 'instance' label.
Migration:
- Update cronjobs: --instance → --server
- Update Grafana dashboard (included) or use new JSON
- Metrics now output server= instead of instance=
Tools submenu expansion:
- Table Sizes: view top 100 tables sorted by size (PG/MySQL)
- Kill Connections: list/kill active DB connections
- Drop Database: safe drop with double confirmation
v3.42.108
- New 'Tools' submenu in TUI with utility functions
- Blob Statistics: scan database for bytea/blob columns with size analysis
- New 'dbbackup blob stats' CLI command
- Supports PostgreSQL (bytea, oid) and MySQL (blob types)
- Shows row counts, total size, avg size, max size per column
- Recommendations for databases with >100MB blob data
- Replaced ╔═╗║╚╝ boxes with clean horizontal line separators
- Consolidated check styles (passed/failed/warning/pending) into styles.go
- Updated restore_preview.go and diagnose_view.go to use global styles
- Consistent visual language: use ═══ separators, not boxes
Bug: These commands used NewChunkIndex(basePath) which derives index
path from dedup-dir, ignoring the explicit --index-db flag.
Fix: Changed to NewChunkIndexAt(getIndexDBPath()) which respects
the --index-db flag, consistent with backup-db, prune, and verify.
Fixes SQLITE_BUSY errors when using CIFS/NFS with local index.
backupGlobals() used cmd.Output() which blocks until completion
even when context is cancelled. Changed to Start/Wait pattern
with proper context handling for immediate Ctrl+C response.
The actual bug: MkdirAll returns success on CIFS/NFS but the directory
isn't immediately visible for file operations.
Fix:
- Verify directory exists with os.Stat after MkdirAll
- Retry loop (5 attempts, 20ms delay) until directory is visible
- Add write retry loop with re-mkdir on failure
- Keep rename retry as fallback
On network filesystems (CIFS/SMB), atomic renames can fail with
'no such file or directory' due to stale directory caches.
Fix:
- Add MkdirAll before rename to refresh directory cache
- Retry rename up to 3 times with 10ms delay
- Re-ensure directory exists on each retry attempt