FIXED: TUI progess status and creating tar archive

This commit is contained in:
2025-11-05 10:29:29 +00:00
parent a8380135cd
commit 2dd41a2b6e
4 changed files with 63 additions and 11 deletions

BIN
dbbackup

Binary file not shown.

View File

@ -374,7 +374,7 @@ func (e *Engine) BackupCluster(ctx context.Context) error {
// Create archive // Create archive
e.printf(" Creating compressed archive...\n") e.printf(" Creating compressed archive...\n")
if err := e.createArchive(tempDir, outputFile); err != nil { if err := e.createArchive(ctx, tempDir, outputFile); err != nil {
quietProgress.Fail(fmt.Sprintf("Failed to create archive: %v", err)) quietProgress.Fail(fmt.Sprintf("Failed to create archive: %v", err))
operation.Fail("Archive creation failed") operation.Fail("Archive creation failed")
return fmt.Errorf("failed to create archive: %w", err) return fmt.Errorf("failed to create archive: %w", err)
@ -672,7 +672,7 @@ func (e *Engine) backupGlobals(ctx context.Context, tempDir string) error {
} }
// createArchive creates a compressed tar archive // createArchive creates a compressed tar archive
func (e *Engine) createArchive(sourceDir, outputFile string) error { func (e *Engine) createArchive(ctx context.Context, sourceDir, outputFile string) error {
// Use pigz for faster parallel compression if available, otherwise use standard gzip // Use pigz for faster parallel compression if available, otherwise use standard gzip
compressCmd := "tar" compressCmd := "tar"
compressArgs := []string{"-czf", outputFile, "-C", sourceDir, "."} compressArgs := []string{"-czf", outputFile, "-C", sourceDir, "."}
@ -681,28 +681,46 @@ func (e *Engine) createArchive(sourceDir, outputFile string) error {
if _, err := exec.LookPath("pigz"); err == nil { if _, err := exec.LookPath("pigz"); err == nil {
// Use pigz with number of cores for parallel compression // Use pigz with number of cores for parallel compression
compressArgs = []string{"-cf", "-", "-C", sourceDir, "."} compressArgs = []string{"-cf", "-", "-C", sourceDir, "."}
cmd := exec.Command("tar", compressArgs...) cmd := exec.CommandContext(ctx, "tar", compressArgs...)
// Pipe to pigz for parallel compression // Create output file
pigzCmd := exec.Command("pigz", "-p", strconv.Itoa(e.cfg.Jobs), ">", outputFile) outFile, err := os.Create(outputFile)
tarOut, err := cmd.StdoutPipe()
if err != nil { if err != nil {
// Fallback to regular tar // Fallback to regular tar
goto regularTar goto regularTar
} }
pigzCmd.Stdin = tarOut defer outFile.Close()
// Pipe to pigz for parallel compression
pigzCmd := exec.CommandContext(ctx, "pigz", "-p", strconv.Itoa(e.cfg.Jobs))
tarOut, err := cmd.StdoutPipe()
if err != nil {
outFile.Close()
// Fallback to regular tar
goto regularTar
}
pigzCmd.Stdin = tarOut
pigzCmd.Stdout = outFile
// Start both commands
if err := pigzCmd.Start(); err != nil { if err := pigzCmd.Start(); err != nil {
outFile.Close()
goto regularTar goto regularTar
} }
if err := cmd.Start(); err != nil { if err := cmd.Start(); err != nil {
pigzCmd.Process.Kill()
outFile.Close()
goto regularTar goto regularTar
} }
// Wait for tar to finish
if err := cmd.Wait(); err != nil { if err := cmd.Wait(); err != nil {
pigzCmd.Process.Kill()
return fmt.Errorf("tar failed: %w", err) return fmt.Errorf("tar failed: %w", err)
} }
// Wait for pigz to finish
if err := pigzCmd.Wait(); err != nil { if err := pigzCmd.Wait(); err != nil {
return fmt.Errorf("pigz compression failed: %w", err) return fmt.Errorf("pigz compression failed: %w", err)
} }
@ -711,7 +729,7 @@ func (e *Engine) createArchive(sourceDir, outputFile string) error {
regularTar: regularTar:
// Standard tar with gzip (fallback) // Standard tar with gzip (fallback)
cmd := exec.Command(compressCmd, compressArgs...) cmd := exec.CommandContext(ctx, compressCmd, compressArgs...)
// Stream stderr to avoid memory issues // Stream stderr to avoid memory issues
stderr, err := cmd.StderrPipe() stderr, err := cmd.StderrPipe()

View File

@ -61,7 +61,18 @@ func (m BackupExecutionModel) Init() tea.Cmd {
}) })
}) })
return executeBackupWithTUIProgress(m.config, m.logger, m.backupType, m.databaseName, m.ratio, reporter) return tea.Batch(
executeBackupWithTUIProgress(m.config, m.logger, m.backupType, m.databaseName, m.ratio, reporter),
backupTickCmd(),
)
}
type backupTickMsg time.Time
func backupTickCmd() tea.Cmd {
return tea.Tick(time.Millisecond*100, func(t time.Time) tea.Msg {
return backupTickMsg(t)
})
} }
type backupProgressMsg struct { type backupProgressMsg struct {
@ -142,6 +153,12 @@ func executeBackupWithTUIProgress(cfg *config.Config, log logger.Logger, backupT
func (m BackupExecutionModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { func (m BackupExecutionModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) { switch msg := msg.(type) {
case backupTickMsg:
if !m.done {
return m, backupTickCmd()
}
return m, nil
case backupProgressMsg: case backupProgressMsg:
m.status = msg.status m.status = msg.status
m.progress = msg.progress m.progress = msg.progress

View File

@ -37,7 +37,18 @@ func NewStatusView(cfg *config.Config, log logger.Logger, parent tea.Model) Stat
} }
func (m StatusViewModel) Init() tea.Cmd { func (m StatusViewModel) Init() tea.Cmd {
return fetchStatus(m.config, m.logger) return tea.Batch(
fetchStatus(m.config, m.logger),
tickCmd(),
)
}
type tickMsg time.Time
func tickCmd() tea.Cmd {
return tea.Tick(time.Millisecond*100, func(t time.Time) tea.Msg {
return tickMsg(t)
})
} }
type statusMsg struct { type statusMsg struct {
@ -98,6 +109,12 @@ func fetchStatus(cfg *config.Config, log logger.Logger) tea.Cmd {
func (m StatusViewModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { func (m StatusViewModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) { switch msg := msg.(type) {
case tickMsg:
if m.loading {
return m, tickCmd()
}
return m, nil
case statusMsg: case statusMsg:
m.loading = false m.loading = false
if msg.status != "" { if msg.status != "" {