@@ -13,7 +13,9 @@ import (
1313 "io"
1414 "os"
1515 "os/exec"
16+ "sort"
1617 "sync"
18+ "time"
1719
1820 pgbackrestapi "github.com/dalibo/cnpg-i-pgbackrest/internal/pgbackrest/api"
1921 "github.com/dalibo/cnpg-i-pgbackrest/internal/utils"
@@ -272,3 +274,69 @@ func (p *PgBackrest) Restore(ctx context.Context) <-chan error {
272274 env = append (env , "PGBACKREST_ARCHIVE_CHECK=n" )
273275 return p .runBackgroundTask (ctx , []string {"restore" }, env )
274276}
277+
278+ func SelectBestBackup (
279+ backups []pgbackrestapi.BackupInfo ,
280+ opts RestoreOptions ,
281+ ) (* pgbackrestapi.BackupInfo , error ) {
282+ if len (backups ) == 0 {
283+ return nil , fmt .Errorf ("no backups available" )
284+ }
285+
286+ // First sort backups from newest to oldest, that way we will
287+ // always match the newest backup
288+ sort .Slice (backups , func (i , j int ) bool {
289+ return backups [i ].Timestamp .Stop > backups [j ].Timestamp .Stop
290+ })
291+
292+ switch opts .Type {
293+ case "name" :
294+ for _ , b := range backups {
295+ if b .Label == opts .Target {
296+ return & b , nil
297+ }
298+ }
299+ return nil , fmt .Errorf ("backup with label %q not found" , opts .Target )
300+
301+ case "time" :
302+ targetTime , err := time .Parse (time .RFC3339 , opts .Target )
303+ if err != nil {
304+ return nil , fmt .Errorf ("invalid target time %q: %w" , opts .Target , err )
305+ }
306+ targetTS := targetTime .Unix ()
307+
308+ for _ , b := range backups {
309+ if b .Timestamp .Stop <= targetTS {
310+ return & b , nil
311+ }
312+ }
313+ return nil , fmt .Errorf ("no backup found before target time %s" , opts .Target )
314+
315+ case "lsn" :
316+ targetLSN , err := utils .ParseLSN (opts .Target )
317+ if err != nil {
318+ return nil , fmt .Errorf ("invalid target LSN %q: %w" , opts .Target , err )
319+ }
320+
321+ for _ , b := range backups {
322+ stopLSN , err := utils .ParseLSN (b .Lsn .Stop )
323+ if err != nil {
324+ continue
325+ }
326+ if stopLSN <= targetLSN {
327+ return & b , nil
328+ }
329+ }
330+ return nil , fmt .Errorf (
331+ "no backup found before target LSN %s" ,
332+ opts .Target ,
333+ )
334+
335+ // decide what to do here
336+ //case "xid":
337+ // return nil, nil
338+
339+ default :
340+ return LatestBackup (backups ), nil
341+ }
342+ }
0 commit comments