High Priority Fixes:
- Use configurable ClusterTimeoutMinutes for restore (was hardcoded 2 hours)
- Add comment explaining goroutine cleanup in stderr reader (cmd.Run waits)
- Add defer cancel() in cluster backup loop to prevent context leak on panic
Medium Priority Fixes:
- Standardize tick rate to 100ms for both backup and restore (consistent UX)
- Add spinnerFrame field to BackupExecutionModel for incremental updates
- Define package-level spinnerFrames constant to avoid repeated allocation
Low Priority Fixes:
- Add 30-second timeout per database in cluster cleanup loop
- Prevents indefinite hangs when dropping many databases
Optimizations:
- Pre-allocate 512 bytes in View() string builders (reduces allocations)
- Use incremental spinner frame calculation (more efficient than time-based)
- Share spinner frames array across all TUI operations
All changes are backward compatible and maintain existing behavior.
Issue: Interactive backup (single, sample, cluster) showed 'Status: Initializing...'
throughout the entire backup process, identical to the restore issue that was just fixed.
Root cause:
- Status was set once in NewBackupExecution()
- Never updated during the backup process
- Only changed to success/failure at completion
- No visual feedback about backup progress
Solution: Time-based status progression (matching restore pattern)
Added logic in Update() tick handler to change status based on elapsed time:
- 0-2 sec: 'Initializing backup...'
- 2-5 sec: Connection phase:
- Cluster: 'Connecting to database cluster...'
- Single/Sample: 'Connecting to database [name]...'
- 5-10 sec: Early backup phase:
- Cluster: 'Backing up global objects (roles, tablespaces)...'
- Sample: 'Analyzing tables for sampling (ratio: N)...'
- Single: 'Dumping database [name]...'
- 10+ sec: Main backup phase:
- Cluster: 'Backing up cluster databases...'
- Sample: 'Creating sample backup of [name]...'
- Single: 'Backing up database [name]...'
Benefits:
- Consistent UX with restore operations
- Different status messages for single/sample/cluster backups
- Shows what stage of backup is running
- Spinner + changing status = clear progress indication
- Better user experience during long cluster backups
Status checked across all TUI operations:
✅ RestoreExecutionModel - Fixed (previous commit)
✅ BackupExecutionModel - Fixed (this commit)
✅ StatusViewModel - Already has proper loading state
✅ OperationsViewModel - Simple view, no long operations