mirror of
https://github.com/rclone/rclone.git
synced 2026-10-28 14:28:38 -04:00
serve restic: fix temporary errors confusing restic into leaving locks behind
deleteObject() replied 404 for any error from newObject(), while serveObject() in the same file replies 404 only for fs.ErrorObjectNotFound and 500 otherwise. restic treats a 404 on DELETE as final and never retries, so a transient lookup failure while removing a lock left the lock behind and broke the next exclusive operation (eg forget --prune failing with "repository is already locked"). This change mirrors serveObject() handling of 404/500 errors in deleteObject(). Fixes #10100 Co-authored-by: bunnysayzz <bunnysayzz@users.noreply.github.com>
This commit is contained in:
1 parent
694dae2ed7
commit
0677b0ca1e
2 files changed
+27
-1
No files matched your search
@@ -509,7 +509,11 @@ func (s *server) deleteObject(w http.ResponseWriter, r *http.Request) {
|
||||
o, err := s.newObject(r.Context(), remote)
|
||||
if err != nil {
|
||||
fs.Debugf(remote, "Delete request error: %v", err)
|
||||
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
||||
if errors.Is(err, fs.ErrorObjectNotFound) {
|
||||
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
||||
} else {
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -229,6 +229,28 @@ func TestServeErrors(t *testing.T) {
|
||||
checkRequest(t, router.ServeHTTP, req, []wantFunc{wantCode(http.StatusNotFound)})
|
||||
}
|
||||
|
||||
func TestDeleteErrors(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
// setup rclone with a local backend in a temporary directory
|
||||
tempdir := t.TempDir()
|
||||
opt := newOpt()
|
||||
|
||||
// make a new file system in the temp dir
|
||||
f := &newObjectErrorFs{Fs: cmd.NewFsSrc([]string{tempdir})}
|
||||
s, err := newServer(ctx, f, &opt)
|
||||
require.NoError(t, err)
|
||||
router := s.server.Router()
|
||||
|
||||
// a lookup failure that is not "not found" must be a 500 so
|
||||
// restic retries the delete instead of treating it as final
|
||||
f.err = errors.New("oops")
|
||||
req := newRequest(t, "DELETE", "/test/locks/0123456789abcdef", nil)
|
||||
checkRequest(t, router.ServeHTTP, req, []wantFunc{wantCode(http.StatusInternalServerError)})
|
||||
|
||||
f.err = fs.ErrorObjectNotFound
|
||||
checkRequest(t, router.ServeHTTP, req, []wantFunc{wantCode(http.StatusNotFound)})
|
||||
}
|
||||
|
||||
func TestRc(t *testing.T) {
|
||||
servetest.TestRc(t, rc.Params{
|
||||
"type": "restic",
|
||||
|
||||
Reference in new issue
Block a user