yandex: fix 500 errors by waiting for uploads to complete before setting modtime

After PUTting a file to the upload URL, Yandex keeps the file locked
for writing until the upload operation finishes committing on the
server. The PUT returned before this happened, so the following
SetModTime raced the still-in-progress write and got spurious 500
Internal Server Error responses.

Capture the operation_id returned with the upload URL and poll the
operation status until it reports success before returning, so the file
is fully committed before we access it.
This commit is contained in:
Nick Craig-Wood
2026-07-12 13:26:39 +01:00
parent 63439b4444
commit fe78b559d1
2 changed files with 13 additions and 4 deletions
+4 -3
View File
@@ -52,9 +52,10 @@ type ResourceListResponse struct {
// AsyncInfo struct is returned by the API for various async operations.
type AsyncInfo struct {
HRef string `json:"href"`
Method string `json:"method"`
Templated bool `json:"templated"`
HRef string `json:"href"`
Method string `json:"method"`
Templated bool `json:"templated"`
OperationID string `json:"operation_id"`
}
// AsyncStatus is returned when requesting the status of an async operations. Possible values in-progress, success, failure
+9 -1
View File
@@ -577,7 +577,7 @@ func (f *Fs) waitForJob(ctx context.Context, location string) (err error) {
}
switch status.Status {
case "failure":
case "failure", "failed":
return fmt.Errorf("async operation returned %q", status.Status)
case "success":
return nil
@@ -1124,6 +1124,14 @@ func (o *Object) upload(ctx context.Context, in io.Reader, overwrite bool, mimeT
resp, err = o.fs.srv.Call(ctx, &opts)
return shouldRetry(ctx, resp, err)
})
if err != nil {
return err
}
// Wait for PUT to be committed
if ur.OperationID != "" {
err = o.fs.waitForJob(ctx, rootURL+"/operations/"+ur.OperationID)
}
return err
}