mirror of
https://github.com/databasus/databasus.git
synced 2026-04-06 00:32:03 +02:00
173 lines
4.0 KiB
Go
173 lines
4.0 KiB
Go
package restores
|
|
|
|
import (
|
|
"errors"
|
|
"log/slog"
|
|
"postgresus-backend/internal/features/backups/backups"
|
|
backups_config "postgresus-backend/internal/features/backups/config"
|
|
"postgresus-backend/internal/features/databases"
|
|
"postgresus-backend/internal/features/restores/enums"
|
|
"postgresus-backend/internal/features/restores/models"
|
|
"postgresus-backend/internal/features/restores/usecases"
|
|
"postgresus-backend/internal/features/storages"
|
|
users_models "postgresus-backend/internal/features/users/models"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type RestoreService struct {
|
|
backupService *backups.BackupService
|
|
restoreRepository *RestoreRepository
|
|
storageService *storages.StorageService
|
|
backupConfigService *backups_config.BackupConfigService
|
|
restoreBackupUsecase *usecases.RestoreBackupUsecase
|
|
logger *slog.Logger
|
|
}
|
|
|
|
func (s *RestoreService) OnBeforeBackupRemove(backup *backups.Backup) error {
|
|
restores, err := s.restoreRepository.FindByBackupID(backup.ID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, restore := range restores {
|
|
if restore.Status == enums.RestoreStatusInProgress {
|
|
return errors.New("restore is in progress, backup cannot be removed")
|
|
}
|
|
}
|
|
|
|
for _, restore := range restores {
|
|
if err := s.restoreRepository.DeleteByID(restore.ID); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *RestoreService) GetRestores(
|
|
user *users_models.User,
|
|
backupID uuid.UUID,
|
|
) ([]*models.Restore, error) {
|
|
backup, err := s.backupService.GetBackup(backupID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if backup.Database.UserID != user.ID {
|
|
return nil, errors.New("user does not have access to this backup")
|
|
}
|
|
|
|
return s.restoreRepository.FindByBackupID(backupID)
|
|
}
|
|
|
|
func (s *RestoreService) RestoreBackupWithAuth(
|
|
user *users_models.User,
|
|
backupID uuid.UUID,
|
|
requestDTO RestoreBackupRequest,
|
|
) error {
|
|
backup, err := s.backupService.GetBackup(backupID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if backup.Database.UserID != user.ID {
|
|
return errors.New("user does not have access to this backup")
|
|
}
|
|
|
|
go func() {
|
|
if err := s.RestoreBackup(backup, requestDTO); err != nil {
|
|
s.logger.Error("Failed to restore backup", "error", err)
|
|
}
|
|
}()
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *RestoreService) RestoreBackup(
|
|
backup *backups.Backup,
|
|
requestDTO RestoreBackupRequest,
|
|
) error {
|
|
if backup.Status != backups.BackupStatusCompleted {
|
|
return errors.New("backup is not completed")
|
|
}
|
|
|
|
if backup.Database.Type == databases.DatabaseTypePostgres {
|
|
if requestDTO.PostgresqlDatabase == nil {
|
|
return errors.New("postgresql database is required")
|
|
}
|
|
}
|
|
|
|
restore := models.Restore{
|
|
ID: uuid.New(),
|
|
Status: enums.RestoreStatusInProgress,
|
|
|
|
BackupID: backup.ID,
|
|
Backup: backup,
|
|
|
|
CreatedAt: time.Now().UTC(),
|
|
RestoreDurationMs: 0,
|
|
|
|
FailMessage: nil,
|
|
}
|
|
|
|
// Save the restore first
|
|
if err := s.restoreRepository.Save(&restore); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Set the RestoreID on the PostgreSQL database and save it
|
|
if requestDTO.PostgresqlDatabase != nil {
|
|
requestDTO.PostgresqlDatabase.RestoreID = &restore.ID
|
|
restore.Postgresql = requestDTO.PostgresqlDatabase
|
|
|
|
// Save the restore again to include the postgresql database
|
|
if err := s.restoreRepository.Save(&restore); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
storage, err := s.storageService.GetStorageByID(backup.StorageID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
backupConfig, err := s.backupConfigService.GetBackupConfigByDbId(
|
|
backup.Database.ID,
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
start := time.Now().UTC()
|
|
|
|
err = s.restoreBackupUsecase.Execute(
|
|
backupConfig,
|
|
restore,
|
|
backup,
|
|
storage,
|
|
)
|
|
if err != nil {
|
|
errMsg := err.Error()
|
|
restore.FailMessage = &errMsg
|
|
restore.Status = enums.RestoreStatusFailed
|
|
restore.RestoreDurationMs = time.Since(start).Milliseconds()
|
|
|
|
if err := s.restoreRepository.Save(&restore); err != nil {
|
|
return err
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
restore.Status = enums.RestoreStatusCompleted
|
|
restore.RestoreDurationMs = time.Since(start).Milliseconds()
|
|
|
|
if err := s.restoreRepository.Save(&restore); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|