From 7c8cd323718d6f65b7eba6dd6d7536b646f8f201 Mon Sep 17 00:00:00 2001 From: Shaun Davis Date: Sat, 6 Jul 2024 09:52:11 -0500 Subject: [PATCH] Restore windows need to work off end-times (#232) --- internal/flypg/barman_restore.go | 43 +++++++-------------------- internal/flypg/barman_restore_test.go | 6 ++-- 2 files changed, 14 insertions(+), 35 deletions(-) diff --git a/internal/flypg/barman_restore.go b/internal/flypg/barman_restore.go index 8ec6d51a..0bd05cce 100644 --- a/internal/flypg/barman_restore.go +++ b/internal/flypg/barman_restore.go @@ -211,64 +211,43 @@ func (*BarmanRestore) resolveBackupFromTime(backupList BackupList, restoreStr st return "", fmt.Errorf("no backups found") } - var restoreTime time.Time - // Parse the restore string restoreTime, err := time.Parse(time.RFC3339, restoreStr) if err != nil { return "", fmt.Errorf("failed to parse restore time: %s", err) } - latestBackupID := "" - latestStartTime := time.Time{} - - earliestBackupID := "" - earliestEndTime := time.Time{} + var lastBackupID string + var lastBackupTime time.Time // This is the layout presented by barman layout := "Mon Jan 2 15:04:05 2006" for _, backup := range backupList.Backups { - // Skip backups that that failed or are in progress // TODO - This shouldn't be needed, but will keep it around until we can improve tests. if backup.Status != "DONE" { continue } - // Parse the backup start time - startTime, err := time.Parse(layout, backup.StartTime) - if err != nil { - return "", fmt.Errorf("failed to parse backup start time: %s", err) - } - // Parse the backup start time + // Parse the backup end time endTime, err := time.Parse(layout, backup.EndTime) if err != nil { return "", fmt.Errorf("failed to parse backup end time: %s", err) } - // Check if the restore time falls within the backup window - if restoreTime.After(startTime) && restoreTime.Before(endTime) { - return backup.BackupID, nil - } - // Track the latest and earliest backups in case the restore time is outside - // the available backup windows - if latestBackupID == "" || startTime.After(latestStartTime) { - latestBackupID = backup.BackupID - latestStartTime = startTime + // If the last backup ID is empty or the restore time is after the last backup time, update the last backup ID. + if lastBackupID == "" || restoreTime.After(endTime) { + lastBackupID = backup.BackupID + lastBackupTime = endTime } - if earliestBackupID == "" || endTime.Before(earliestEndTime) { - earliestBackupID = backup.BackupID - earliestEndTime = endTime + // If the restore time is after the backup end time, we can short-circuit and return the last backup. + if endTime.After(lastBackupTime) { + return lastBackupID, nil } } - // if the restore time is before the earliest backup, restore the earliest backup - if restoreTime.Before(earliestEndTime) { - return earliestBackupID, nil - } - - return latestBackupID, nil + return lastBackupID, nil } func waitOnRecovery(ctx context.Context, privateIP string) error { diff --git a/internal/flypg/barman_restore_test.go b/internal/flypg/barman_restore_test.go index b6f3f32f..45978565 100644 --- a/internal/flypg/barman_restore_test.go +++ b/internal/flypg/barman_restore_test.go @@ -328,8 +328,8 @@ func TestResolveBackupTarget(t *testing.T) { t.Fatalf("unexpected error: %v", err) } - t.Run("resolve-earliest-backup-target", func(t *testing.T) { - backupID, err := restore.resolveBackupFromTime(list, "2024-06-25T19:44:12-00:00") + t.Run("resolve-oldest-target", func(t *testing.T) { + backupID, err := restore.resolveBackupFromTime(list, "2024-06-25T19:40:18-00:00") if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -351,7 +351,7 @@ func TestResolveBackupTarget(t *testing.T) { }) t.Run("resolve-backup-within-second-window", func(t *testing.T) { - backupID, err := restore.resolveBackupFromTime(list, "2024-06-26T17:25:15-00:00") + backupID, err := restore.resolveBackupFromTime(list, "2024-06-26T17:29:15-00:00") if err != nil { t.Fatalf("unexpected error: %v", err) }