From 04b4f3935ec3df95d401b30890da7f97f32a267d Mon Sep 17 00:00:00 2001 From: ashmrtn <3891298+ashmrtn@users.noreply.github.com> Date: Wed, 3 Aug 2022 12:05:35 -0700 Subject: [PATCH] Use different method to get kopia write session (#474) Kopia maintainer mentioned this was a better way to deal with it than the old version. Mostly superficial changes to logic. Always safe to flush the write session during an upload. That will ensure write sessions are closed. Validity of the uploaded data will be via reachability of the data in the repo. Drawback is if there's a problem flushing the write session it will return that error instead of the original error (if there was one) --- src/internal/kopia/wrapper.go | 75 ++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 28 deletions(-) diff --git a/src/internal/kopia/wrapper.go b/src/internal/kopia/wrapper.go index 18c4f4447..dca7bd715 100644 --- a/src/internal/kopia/wrapper.go +++ b/src/internal/kopia/wrapper.go @@ -254,35 +254,54 @@ func (w Wrapper) makeSnapshotWithRoot( root fs.Directory, details *details.Details, ) (*BackupStats, error) { - si := snapshot.SourceInfo{ - Host: corsoHost, - UserName: corsoUser, - // TODO(ashmrtnz): will this be something useful for snapshot lookups later? - Path: root.Name(), - } - ctx, rw, err := w.c.NewWriter(ctx, repo.WriteSessionOptions{}) + var man *snapshot.Manifest + + err := repo.WriteSession( + ctx, + w.c, + repo.WriteSessionOptions{ + Purpose: "KopiaWrapperBackup", + // Always flush so we don't leak write sessions. Still uses reachability + // for consistency. + FlushOnFailure: true, + }, + func(innerCtx context.Context, rw repo.RepositoryWriter) error { + si := snapshot.SourceInfo{ + Host: corsoHost, + UserName: corsoUser, + // TODO(ashmrtnz): will this be something useful for snapshot lookups later? + Path: root.Name(), + } + + policyTree, err := policy.TreeForSource(innerCtx, w.c, si) + if err != nil { + err = errors.Wrap(err, "get policy tree") + logger.Ctx(innerCtx).Errorw("kopia backup", err) + return err + } + + u := snapshotfs.NewUploader(rw) + man, err = u.Upload(innerCtx, root, policyTree, si) + if err != nil { + err = errors.Wrap(err, "uploading data") + logger.Ctx(innerCtx).Errorw("kopia backup", err) + return err + } + + if _, err := snapshot.SaveSnapshot(innerCtx, rw, man); err != nil { + err = errors.Wrap(err, "saving snapshot") + logger.Ctx(innerCtx).Errorw("kopia backup", err) + return err + } + + return nil + }, + ) + + // Telling kopia to always flush may hide other errors if it fails while + // flushing the write session (hence logging above). if err != nil { - return nil, errors.Wrap(err, "get repo writer") - } - - policyTree, err := policy.TreeForSource(ctx, w.c, si) - if err != nil { - return nil, errors.Wrap(err, "get policy tree") - } - - u := snapshotfs.NewUploader(rw) - - man, err := u.Upload(ctx, root, policyTree, si) - if err != nil { - return nil, errors.Wrap(err, "uploading data") - } - - if _, err := snapshot.SaveSnapshot(ctx, rw, man); err != nil { - return nil, errors.Wrap(err, "saving snapshot") - } - - if err := rw.Flush(ctx); err != nil { - return nil, errors.Wrap(err, "flushing writer") + return nil, errors.Wrap(err, "kopia backup") } res := manifestToStats(man)