132 lines
4.1 KiB
Go
132 lines
4.1 KiB
Go
package backup
|
|
|
|
import (
|
|
"backea/internal/mail"
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"sync"
|
|
)
|
|
|
|
// PerformBackups executes backups for multiple services based on configuration
|
|
func PerformBackups(ctx context.Context, configPath string, serviceName string, serviceIndex string) error {
|
|
// Create backup factory
|
|
factory, err := NewBackupFactory(configPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Initialize mailer
|
|
mailer := mail.NewMailer()
|
|
|
|
// Process services
|
|
if serviceName != "" {
|
|
// Process single service group or specific service
|
|
if serviceIndex != "" {
|
|
// Process specific service within a group
|
|
return processSpecificService(ctx, factory, serviceName, serviceIndex, mailer)
|
|
} else {
|
|
// Process all services in the specified group
|
|
return processServiceGroup(ctx, factory, serviceName, mailer)
|
|
}
|
|
} else {
|
|
// Process all service groups in parallel
|
|
var wg sync.WaitGroup
|
|
errs := make(chan error, len(factory.Config.Services))
|
|
for groupName := range factory.Config.Services {
|
|
wg.Add(1)
|
|
go func(group string) {
|
|
defer wg.Done()
|
|
if err := processServiceGroup(ctx, factory, group, mailer); err != nil {
|
|
log.Printf("Failed to backup service group %s: %v", group, err)
|
|
errs <- fmt.Errorf("backup failed for group %s: %w", group, err)
|
|
}
|
|
}(groupName)
|
|
}
|
|
// Wait for all backups to complete
|
|
wg.Wait()
|
|
close(errs)
|
|
|
|
// Check if any errors occurred
|
|
var lastErr error
|
|
for err := range errs {
|
|
lastErr = err
|
|
}
|
|
return lastErr
|
|
}
|
|
}
|
|
|
|
// processServiceGroup handles the backup for all services in a group
|
|
func processServiceGroup(ctx context.Context, factory *BackupFactory, groupName string, mailer *mail.Mailer) error {
|
|
// Get service group configuration
|
|
serviceGroup, exists := factory.Config.Services[groupName]
|
|
if !exists {
|
|
log.Printf("Service group not found: %s", groupName)
|
|
return nil
|
|
}
|
|
|
|
// Execute the before hook once for the entire group
|
|
if serviceGroup.Hooks.BeforeHook != "" {
|
|
log.Printf("Executing before hook for group %s: %s", groupName, serviceGroup.Hooks.BeforeHook)
|
|
if err := RunCommand(serviceGroup.Source.Path, serviceGroup.Hooks.BeforeHook); err != nil {
|
|
log.Printf("Failed to execute before hook for group %s: %v", groupName, err)
|
|
return err
|
|
}
|
|
}
|
|
|
|
// Process all services in the group in parallel
|
|
var wg sync.WaitGroup
|
|
errs := make(chan error, len(serviceGroup.BackupConfigs))
|
|
for configIndex := range serviceGroup.BackupConfigs {
|
|
wg.Add(1)
|
|
go func(group, index string) {
|
|
defer wg.Done()
|
|
if err := processSpecificService(ctx, factory, group, index, mailer); err != nil {
|
|
log.Printf("Failed to backup service %s.%s: %v", group, index, err)
|
|
errs <- fmt.Errorf("backup failed for %s.%s: %w", group, index, err)
|
|
}
|
|
}(groupName, configIndex)
|
|
}
|
|
// Wait for all backups to complete
|
|
wg.Wait()
|
|
close(errs)
|
|
|
|
// Execute the after hook once for the entire group
|
|
if serviceGroup.Hooks.AfterHook != "" {
|
|
log.Printf("Executing after hook for group %s: %s", groupName, serviceGroup.Hooks.AfterHook)
|
|
if err := RunCommand(serviceGroup.Source.Path, serviceGroup.Hooks.AfterHook); err != nil {
|
|
log.Printf("Failed to execute after hook for group %s: %v", groupName, err)
|
|
// We don't return here because we want to process the errors from the backups
|
|
}
|
|
}
|
|
|
|
// Check if any errors occurred
|
|
var lastErr error
|
|
for err := range errs {
|
|
lastErr = err
|
|
}
|
|
return lastErr
|
|
}
|
|
|
|
// processSpecificService handles the backup for a specific service in a group
|
|
func processSpecificService(ctx context.Context, factory *BackupFactory, groupName string, configIndex string, mailer *mail.Mailer) error {
|
|
// Get service configuration
|
|
serviceGroup := factory.Config.Services[groupName]
|
|
|
|
// Create the appropriate backup strategy using the factory
|
|
strategy, err := factory.CreateBackupStrategyForService(groupName, configIndex)
|
|
if err != nil {
|
|
log.Printf("Failed to create backup strategy for service %s.%s: %v", groupName, configIndex, err)
|
|
return err
|
|
}
|
|
|
|
// Create and run service
|
|
service := NewService(
|
|
fmt.Sprintf("%s.%s", groupName, configIndex),
|
|
serviceGroup.Source.Path,
|
|
strategy,
|
|
mailer,
|
|
)
|
|
return service.Backup(ctx)
|
|
}
|