83 lines
2 KiB
Go
83 lines
2 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"go.uber.org/zap"
|
|
"gorm.io/gorm"
|
|
|
|
"veza-backend-api/internal/models"
|
|
)
|
|
|
|
// CloudBackupWorker copies cloud files to backup prefix periodically
|
|
type CloudBackupWorker struct {
|
|
db *gorm.DB
|
|
s3Service *S3StorageService
|
|
logger *zap.Logger
|
|
interval time.Duration
|
|
}
|
|
|
|
// NewCloudBackupWorker creates a new backup worker
|
|
func NewCloudBackupWorker(db *gorm.DB, s3Service *S3StorageService, logger *zap.Logger) *CloudBackupWorker {
|
|
return &CloudBackupWorker{
|
|
db: db,
|
|
s3Service: s3Service,
|
|
logger: logger,
|
|
interval: 24 * time.Hour,
|
|
}
|
|
}
|
|
|
|
// Start runs the backup loop
|
|
func (w *CloudBackupWorker) Start(ctx context.Context) {
|
|
if w.s3Service == nil {
|
|
w.logger.Info("Cloud backup worker: S3 not configured, skipping")
|
|
return
|
|
}
|
|
|
|
ticker := time.NewTicker(w.interval)
|
|
defer ticker.Stop()
|
|
|
|
w.logger.Info("Cloud backup worker started", zap.Duration("interval", w.interval))
|
|
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
case <-ticker.C:
|
|
if err := w.runBackup(ctx); err != nil {
|
|
w.logger.Error("Cloud backup failed", zap.Error(err))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (w *CloudBackupWorker) runBackup(ctx context.Context) error {
|
|
prefix := "backup/" + time.Now().Format("2006-01-02") + "/"
|
|
|
|
var files []models.UserFile
|
|
if err := w.db.WithContext(ctx).Find(&files).Error; err != nil {
|
|
return fmt.Errorf("list files: %w", err)
|
|
}
|
|
|
|
copied := 0
|
|
for _, f := range files {
|
|
backupKey := prefix + f.S3Key
|
|
data, err := w.s3Service.DownloadFile(ctx, f.S3Key)
|
|
if err != nil {
|
|
w.logger.Warn("backup: skip file", zap.String("key", f.S3Key), zap.Error(err))
|
|
continue
|
|
}
|
|
if _, err := w.s3Service.UploadFile(ctx, data, backupKey, f.MimeType); err != nil {
|
|
w.logger.Warn("backup: upload failed", zap.String("key", backupKey), zap.Error(err))
|
|
continue
|
|
}
|
|
copied++
|
|
}
|
|
|
|
if copied > 0 {
|
|
w.logger.Info("Cloud backup completed", zap.Int("files_copied", copied), zap.String("prefix", prefix))
|
|
}
|
|
return nil
|
|
}
|