From 257740b0cca7a8ae8c1007711182e1b58208fb7d Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Sat, 9 Oct 2021 22:57:34 +0200 Subject: [PATCH] b2: Successful delete if file does not exist When deleting a file, B2 sometimes returns a "500 Service Unavailable" error but nevertheless correctly deletes the file. Due to retries in the B2 library blazer, we sometimes also see a "400 File not present" error. The retries of restic for the delete request then fail with "404 File with such name does not exist.". As we have to rely on request retries in a distributed system to handle temporary errors, also consider a delete request to be successful if the file is reported as not existing. This should be safe as B2 claims to provide a strongly consistent bucket listing and thus a missing file shouldn't mysteriously show up again later on. --- changelog/unreleased/issue-3541 | 9 +++++++++ internal/backend/b2/b2.go | 8 +++++++- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 changelog/unreleased/issue-3541 diff --git a/changelog/unreleased/issue-3541 b/changelog/unreleased/issue-3541 new file mode 100644 index 000000000..ea20949d7 --- /dev/null +++ b/changelog/unreleased/issue-3541 @@ -0,0 +1,9 @@ +Bugfix: Improve handling of temporary B2 delete errors + +Deleting files on B2 can sometimes fail temporarily, which requires restic to +retry the delete operation. In some cases the file was deleted nevertheless +causing the retries and ultimately the restic command to fail. This has been +fixed. + +https://github.com/restic/restic/issues/3541 +https://github.com/restic/restic/pull/3544 diff --git a/internal/backend/b2/b2.go b/internal/backend/b2/b2.go index 8d4116452..90aeca3b2 100644 --- a/internal/backend/b2/b2.go +++ b/internal/backend/b2/b2.go @@ -265,7 +265,13 @@ func (be *b2Backend) Remove(ctx context.Context, h restic.Handle) error { defer be.sem.ReleaseToken() obj := be.bucket.Object(be.Filename(h)) - return errors.Wrap(obj.Delete(ctx), "Delete") + err := obj.Delete(ctx) + // consider a file as removed if b2 informs us that it does not exist + if b2.IsNotExist(err) { + return nil + } + + return errors.Wrap(err, "Delete") } type semLocker struct {