feat(tui): add resource profiles for backup/restore operations
All checks were successful
CI/CD / Test (push) Successful in 1m17s
CI/CD / Lint (push) Successful in 1m25s
CI/CD / Build & Release (push) Successful in 3m15s

- Add memory detection for Linux, macOS, Windows
- Add 5 predefined profiles: conservative, balanced, performance, max-performance, large-db
- Add Resource Profile and Cluster Parallelism settings in TUI
- Add quick hotkeys: 'l' for large-db, 'c' for conservative, 'p' for recommendations
- Display system resources (CPU cores, memory) and recommended profile
- Auto-detect and recommend profile based on system resources

Fixes 'out of shared memory' errors when restoring large databases on small VMs.
Use 'large-db' or 'conservative' profile for large databases on constrained systems.
This commit is contained in:
2026-01-18 11:38:24 +01:00
parent e2cf9adc62
commit 670c9af2e7
4 changed files with 629 additions and 7 deletions

View File

@@ -36,9 +36,13 @@ type Config struct {
AutoDetectCores bool
CPUWorkloadType string // "cpu-intensive", "io-intensive", "balanced"
// Resource profile for backup/restore operations
ResourceProfile string // "conservative", "balanced", "performance", "max-performance", "large-db"
// CPU detection
CPUDetector *cpu.Detector
CPUInfo *cpu.CPUInfo
MemoryInfo *cpu.MemoryInfo // System memory information
// Sample backup options
SampleStrategy string // "ratio", "percent", "count"
@@ -178,6 +182,13 @@ func New() *Config {
sslMode = ""
}
// Detect memory information
memInfo, _ := cpu.DetectMemory()
// Determine recommended resource profile
recommendedProfile := cpu.RecommendProfile(cpuInfo, memInfo, false)
defaultProfile := getEnvString("RESOURCE_PROFILE", recommendedProfile.Name)
cfg := &Config{
// Database defaults
Host: host,
@@ -197,10 +208,12 @@ func New() *Config {
MaxCores: getEnvInt("MAX_CORES", getDefaultMaxCores(cpuInfo)),
AutoDetectCores: getEnvBool("AUTO_DETECT_CORES", true),
CPUWorkloadType: getEnvString("CPU_WORKLOAD_TYPE", "balanced"),
ResourceProfile: defaultProfile,
// CPU detection
// CPU and memory detection
CPUDetector: cpuDetector,
CPUInfo: cpuInfo,
MemoryInfo: memInfo,
// Sample backup defaults
SampleStrategy: getEnvString("SAMPLE_STRATEGY", "ratio"),
@@ -409,6 +422,45 @@ func (c *Config) OptimizeForCPU() error {
return nil
}
// ApplyResourceProfile applies a resource profile to the configuration
// This adjusts parallelism settings based on the chosen profile
func (c *Config) ApplyResourceProfile(profileName string) error {
profile := cpu.GetProfileByName(profileName)
if profile == nil {
return &ConfigError{
Field: "resource_profile",
Value: profileName,
Message: "unknown profile. Valid profiles: conservative, balanced, performance, max-performance, large-db",
}
}
// Validate profile against current system
isValid, warnings := cpu.ValidateProfileForSystem(profile, c.CPUInfo, c.MemoryInfo)
if !isValid {
// Log warnings but don't block - user may know what they're doing
_ = warnings // In production, log these warnings
}
// Apply profile settings
c.ResourceProfile = profile.Name
c.ClusterParallelism = profile.ClusterParallelism
c.Jobs = profile.Jobs
c.DumpJobs = profile.DumpJobs
return nil
}
// GetResourceProfileRecommendation returns the recommended profile and reason
func (c *Config) GetResourceProfileRecommendation(isLargeDB bool) (string, string) {
profile, reason := cpu.RecommendProfileWithReason(c.CPUInfo, c.MemoryInfo, isLargeDB)
return profile.Name, reason
}
// GetCurrentProfile returns the current resource profile details
func (c *Config) GetCurrentProfile() *cpu.ResourceProfile {
return cpu.GetProfileByName(c.ResourceProfile)
}
// GetCPUInfo returns CPU information, detecting if necessary
func (c *Config) GetCPUInfo() (*cpu.CPUInfo, error) {
if c.CPUInfo != nil {