fix:goroutines
This commit is contained in:
@@ -87,9 +87,23 @@ func (m BackupManagerModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
// Delete archive (with confirmation)
|
// Delete archive (with confirmation)
|
||||||
if len(m.archives) > 0 && m.cursor < len(m.archives) {
|
if len(m.archives) > 0 && m.cursor < len(m.archives) {
|
||||||
selected := m.archives[m.cursor]
|
selected := m.archives[m.cursor]
|
||||||
confirm := NewConfirmationModel(m.config, m.logger, m,
|
archivePath := selected.Path
|
||||||
|
confirm := NewConfirmationModelWithAction(m.config, m.logger, m,
|
||||||
"🗑️ Delete Archive",
|
"🗑️ Delete Archive",
|
||||||
fmt.Sprintf("Delete archive '%s'? This cannot be undone.", selected.Name))
|
fmt.Sprintf("Delete archive '%s'? This cannot be undone.", selected.Name),
|
||||||
|
func() (tea.Model, tea.Cmd) {
|
||||||
|
// Delete the archive
|
||||||
|
err := deleteArchive(archivePath)
|
||||||
|
if err != nil {
|
||||||
|
m.err = fmt.Errorf("failed to delete archive: %v", err)
|
||||||
|
m.message = fmt.Sprintf("❌ Failed to delete: %v", err)
|
||||||
|
} else {
|
||||||
|
m.message = fmt.Sprintf("✅ Deleted: %s", selected.Name)
|
||||||
|
}
|
||||||
|
// Refresh the archive list
|
||||||
|
m.loading = true
|
||||||
|
return m, loadArchives(m.config, m.logger)
|
||||||
|
})
|
||||||
return confirm, nil
|
return confirm, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,14 +12,15 @@ import (
|
|||||||
|
|
||||||
// ConfirmationModel for yes/no confirmations
|
// ConfirmationModel for yes/no confirmations
|
||||||
type ConfirmationModel struct {
|
type ConfirmationModel struct {
|
||||||
config *config.Config
|
config *config.Config
|
||||||
logger logger.Logger
|
logger logger.Logger
|
||||||
parent tea.Model
|
parent tea.Model
|
||||||
title string
|
title string
|
||||||
message string
|
message string
|
||||||
cursor int
|
cursor int
|
||||||
choices []string
|
choices []string
|
||||||
confirmed bool
|
confirmed bool
|
||||||
|
onConfirm func() (tea.Model, tea.Cmd) // Callback when confirmed
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConfirmationModel(cfg *config.Config, log logger.Logger, parent tea.Model, title, message string) ConfirmationModel {
|
func NewConfirmationModel(cfg *config.Config, log logger.Logger, parent tea.Model, title, message string) ConfirmationModel {
|
||||||
@@ -33,6 +34,18 @@ func NewConfirmationModel(cfg *config.Config, log logger.Logger, parent tea.Mode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewConfirmationModelWithAction(cfg *config.Config, log logger.Logger, parent tea.Model, title, message string, onConfirm func() (tea.Model, tea.Cmd)) ConfirmationModel {
|
||||||
|
return ConfirmationModel{
|
||||||
|
config: cfg,
|
||||||
|
logger: log,
|
||||||
|
parent: parent,
|
||||||
|
title: title,
|
||||||
|
message: message,
|
||||||
|
choices: []string{"Yes", "No"},
|
||||||
|
onConfirm: onConfirm,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (m ConfirmationModel) Init() tea.Cmd {
|
func (m ConfirmationModel) Init() tea.Cmd {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -57,7 +70,11 @@ func (m ConfirmationModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
case "enter", "y":
|
case "enter", "y":
|
||||||
if msg.String() == "y" || m.cursor == 0 {
|
if msg.String() == "y" || m.cursor == 0 {
|
||||||
m.confirmed = true
|
m.confirmed = true
|
||||||
// Execute cluster backup
|
// Execute the onConfirm callback if provided
|
||||||
|
if m.onConfirm != nil {
|
||||||
|
return m.onConfirm()
|
||||||
|
}
|
||||||
|
// Default: execute cluster backup for backward compatibility
|
||||||
executor := NewBackupExecution(m.config, m.logger, m.parent, "cluster", "", 0)
|
executor := NewBackupExecution(m.config, m.logger, m.parent, "cluster", "", 0)
|
||||||
return executor, executor.Init()
|
return executor, executor.Init()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -324,9 +324,13 @@ func (m MenuModel) handleClusterBackup() (tea.Model, tea.Cmd) {
|
|||||||
m.message = errorStyle.Render("❌ Cluster backup is available only for PostgreSQL targets")
|
m.message = errorStyle.Render("❌ Cluster backup is available only for PostgreSQL targets")
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
confirm := NewConfirmationModel(m.config, m.logger, m,
|
confirm := NewConfirmationModelWithAction(m.config, m.logger, m,
|
||||||
"🗄️ Cluster Backup",
|
"🗄️ Cluster Backup",
|
||||||
"This will backup ALL databases in the cluster. Continue?")
|
"This will backup ALL databases in the cluster. Continue?",
|
||||||
|
func() (tea.Model, tea.Cmd) {
|
||||||
|
executor := NewBackupExecution(m.config, m.logger, m, "cluster", "", 0)
|
||||||
|
return executor, executor.Init()
|
||||||
|
})
|
||||||
return confirm, nil
|
return confirm, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,47 @@ func NewSettingsModel(cfg *config.Config, log logger.Logger, parent tea.Model) S
|
|||||||
Type: "selector",
|
Type: "selector",
|
||||||
Description: "Target database engine (press Enter to cycle: PostgreSQL → MySQL → MariaDB)",
|
Description: "Target database engine (press Enter to cycle: PostgreSQL → MySQL → MariaDB)",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Key: "cpu_workload",
|
||||||
|
DisplayName: "CPU Workload Type",
|
||||||
|
Value: func(c *config.Config) string { return c.CPUWorkloadType },
|
||||||
|
Update: func(c *config.Config, v string) error {
|
||||||
|
workloads := []string{"balanced", "cpu-intensive", "io-intensive"}
|
||||||
|
currentIdx := 0
|
||||||
|
for i, w := range workloads {
|
||||||
|
if c.CPUWorkloadType == w {
|
||||||
|
currentIdx = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nextIdx := (currentIdx + 1) % len(workloads)
|
||||||
|
c.CPUWorkloadType = workloads[nextIdx]
|
||||||
|
|
||||||
|
// Recalculate Jobs and DumpJobs based on workload type
|
||||||
|
if c.CPUInfo != nil && c.AutoDetectCores {
|
||||||
|
switch c.CPUWorkloadType {
|
||||||
|
case "cpu-intensive":
|
||||||
|
c.Jobs = c.CPUInfo.PhysicalCores * 2
|
||||||
|
c.DumpJobs = c.CPUInfo.PhysicalCores
|
||||||
|
case "io-intensive":
|
||||||
|
c.Jobs = c.CPUInfo.PhysicalCores / 2
|
||||||
|
if c.Jobs < 1 {
|
||||||
|
c.Jobs = 1
|
||||||
|
}
|
||||||
|
c.DumpJobs = 2
|
||||||
|
default: // balanced
|
||||||
|
c.Jobs = c.CPUInfo.PhysicalCores
|
||||||
|
c.DumpJobs = c.CPUInfo.PhysicalCores / 2
|
||||||
|
if c.DumpJobs < 2 {
|
||||||
|
c.DumpJobs = 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
Type: "selector",
|
||||||
|
Description: "CPU workload profile (press Enter to cycle: Balanced → CPU-Intensive → I/O-Intensive)",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Key: "backup_dir",
|
Key: "backup_dir",
|
||||||
DisplayName: "Backup Directory",
|
DisplayName: "Backup Directory",
|
||||||
|
|||||||
Reference in New Issue
Block a user