protondrive: fix long hangs on permanent validation failures
shouldRetry treated every Code=200501 API error as a transient storage block error and retried it. Proton also returns Code=200501 with an HTTP 422 for permanent validation failures (e.g. a content key packet that cannot be verified, or an upload format the account is not enabled for), so these were retried until the operation timed out causing a multi-minute hang. This fixes it by only retrying Code=200501 when it is not a permanent client (4xx) error.
This commit is contained in:
@@ -264,9 +264,14 @@ func shouldRetry(ctx context.Context, err error) (bool, error) {
|
|||||||
}
|
}
|
||||||
var apiErr *proton.APIError
|
var apiErr *proton.APIError
|
||||||
if errors.As(err, &apiErr) {
|
if errors.As(err, &apiErr) {
|
||||||
// Transient storage block error ("Please retry").
|
// Code 200501 is a generic Drive operation-failure code. Proton also
|
||||||
if apiErr.Code == 200501 {
|
// returns it with an HTTP 422 for permanent validation failures (for
|
||||||
fs.Debugf(nil, "Retrying storage block error: %v", err)
|
// example a content key packet that cannot be verified, or an upload
|
||||||
|
// format the account is not enabled for), which must NOT be retried -
|
||||||
|
// doing so spins the pacer until the operation times out. Only retry it
|
||||||
|
// when it is not a permanent client (4xx) error.
|
||||||
|
if apiErr.Code == 200501 && (apiErr.Status < 400 || apiErr.Status >= 500) {
|
||||||
|
fs.Debugf(nil, "Retrying transient storage block error: %v", err)
|
||||||
return true, err
|
return true, err
|
||||||
}
|
}
|
||||||
// Server errors. 503 is already handled by the SDK; retry the rest.
|
// Server errors. 503 is already handled by the SDK; retry the rest.
|
||||||
|
|||||||
@@ -77,7 +77,8 @@ func TestShouldRetry(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{"nil error", ctx, nil, false},
|
{"nil error", ctx, nil, false},
|
||||||
{"cancelled context", cancelledCtx, errors.New("some error"), false},
|
{"cancelled context", cancelledCtx, errors.New("some error"), false},
|
||||||
{"storage block error Code=200501", ctx, apiErr(422, 200501), true},
|
{"permanent validation error Code=200501 Status=422 (not retried)", ctx, apiErr(422, 200501), false},
|
||||||
|
{"transient storage block error Code=200501 Status=500 (retried)", ctx, apiErr(500, 200501), true},
|
||||||
{"server error Status=500", ctx, apiErr(500, 0), true},
|
{"server error Status=500", ctx, apiErr(500, 0), true},
|
||||||
{"server error Status=502", ctx, apiErr(502, 0), true},
|
{"server error Status=502", ctx, apiErr(502, 0), true},
|
||||||
{"server error Status=504", ctx, apiErr(504, 0), true},
|
{"server error Status=504", ctx, apiErr(504, 0), true},
|
||||||
|
|||||||
Reference in New Issue
Block a user