diff --git a/internal/cnpgi/common/wal.go b/internal/cnpgi/common/wal.go index bb7d3e0..fc974cd 100644 --- a/internal/cnpgi/common/wal.go +++ b/internal/cnpgi/common/wal.go @@ -21,7 +21,6 @@ package common import ( "context" - "errors" "fmt" "os" "path" @@ -331,9 +330,14 @@ func (w WALServiceImplementation) restoreFromBarmanObjectStore( return nil } + // Step 2: return error if the end-of-wal-stream flag is set. + // PostgreSQL treats a restore_command failure as "WAL not available from + // archive" and can then try streaming via primary_conninfo. When prefetch has + // already observed archive exhaustion for this timeline, return one failure to + // let PostgreSQL switch sources instead of repeatedly probing the archive. // We skip this step if streaming connection is not available if isStreamingAvailable(cluster, w.InstanceName) { - if err := checkEndOfWALStreamFlag(walRestorer); err != nil { + if err := checkEndOfWALStreamFlag(walRestorer, walName); err != nil { return err } } @@ -366,15 +370,15 @@ func (w WALServiceImplementation) restoreFromBarmanObjectStore( } // We skip this step if streaming connection is not available - endOfWALStream := isEndOfWALStream(walStatus) - if isStreamingAvailable(cluster, w.InstanceName) && endOfWALStream { - contextLogger.Info( - "Set end-of-wal-stream flag as one of the WAL files to be prefetched was not found") - - err = walRestorer.SetEndOfWALStream() + if isStreamingAvailable(cluster, w.InstanceName) { + endOfWALStream, err := walRestorer.SetEndOfWALStreamFromResults(walStatus) if err != nil { return err } + if endOfWALStream { + contextLogger.Info( + "Set end-of-wal-stream flag as one of the WAL files to be prefetched was not found") + } } successfulWalRestore := 0 @@ -473,32 +477,14 @@ func gatherWALFilesToRestore(walName string, parallel int) (walList []string, er return walList, err } -// checkEndOfWALStreamFlag returns ErrEndOfWALStreamReached if the flag is set in the restorer. -func checkEndOfWALStreamFlag(walRestorer *barmanRestorer.WALRestorer) error { - contain, err := walRestorer.IsEndOfWALStream() +// checkEndOfWALStreamFlag returns ErrEndOfWALStreamReached if the flag is set for the requested WAL timeline. +func checkEndOfWALStreamFlag(walRestorer *barmanRestorer.WALRestorer, walName string) error { + contains, err := walRestorer.ConsumeEndOfWALStreamForWAL(walName) if err != nil { return err } - - if contain { - err := walRestorer.ResetEndOfWalStream() - if err != nil { - return err - } - + if contains { return ErrEndOfWALStreamReached } return nil } - -// isEndOfWALStream returns true if one of the downloads has returned -// a file-not-found error. -func isEndOfWALStream(results []barmanRestorer.Result) bool { - for _, result := range results { - if errors.Is(result.Err, barmanRestorer.ErrWALNotFound) { - return true - } - } - - return false -}