forked from cockroachdb/cockroach
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cloud/gcp: add custom retryer for gcs storage, retry on stream INTERN…
…AL_ERROR Currently, errors like `stream error: stream ID <x>; INTERNAL_ERROR; received from peer` are not being retried. Create a custom retryer to retry these errors as suggested by: googleapis/google-cloud-go#3735 googleapis/google-cloud-go#784 Fixes: cockroachdb#85217, cockroachdb#85216, cockroachdb#85204, cockroachdb#84162 Release note: None
- Loading branch information
Rui Hu
committed
Jul 29, 2022
1 parent
1c90519
commit cb92673
Showing
5 changed files
with
117 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
// Copyright 2022 The Cockroach Authors. | ||
// | ||
// Use of this software is governed by the Business Source License | ||
// included in the file licenses/BSL.txt. | ||
// | ||
// As of the Change Date specified in that file, in accordance with | ||
// the Business Source License, use of this software will be governed | ||
// by the Apache License, Version 2.0, included in the file | ||
// licenses/APL.txt. | ||
|
||
package gcp | ||
|
||
import ( | ||
"io" | ||
"net" | ||
"net/url" | ||
"strings" | ||
|
||
"github.com/cockroachdb/errors" | ||
"google.golang.org/api/googleapi" | ||
"google.golang.org/grpc/codes" | ||
"google.golang.org/grpc/status" | ||
) | ||
|
||
// defaultShouldRetry is google-cloud's default predicate for determining | ||
// whether an error can be retried. | ||
// | ||
// TODO(rui): Currently this code is copied as-is from the google-cloud-go SDK | ||
// in order to get the default retry behavior on top of our own customizations. | ||
// There's currently a PR in google-cloud-go that exposes the default retry | ||
// function, so this can be removed when it is merged: | ||
// https://github.com/googleapis/google-cloud-go/pull/6370 | ||
func defaultShouldRetry(err error) bool { | ||
if err == nil { | ||
return false | ||
} | ||
if errors.Is(err, io.ErrUnexpectedEOF) { | ||
return true | ||
} | ||
|
||
switch e := err.(type) { | ||
case *net.OpError: | ||
if strings.Contains(e.Error(), "use of closed network connection") { | ||
// TODO: check against net.ErrClosed (go 1.16+) instead of string | ||
return true | ||
} | ||
case *googleapi.Error: | ||
// Retry on 408, 429, and 5xx, according to | ||
// https://cloud.google.com/storage/docs/exponential-backoff. | ||
return e.Code == 408 || e.Code == 429 || (e.Code >= 500 && e.Code < 600) | ||
case *url.Error: | ||
// Retry socket-level errors ECONNREFUSED and ECONNRESET (from syscall). | ||
// Unfortunately the error type is unexported, so we resort to string | ||
// matching. | ||
retriable := []string{"connection refused", "connection reset"} | ||
for _, s := range retriable { | ||
if strings.Contains(e.Error(), s) { | ||
return true | ||
} | ||
} | ||
case interface{ Temporary() bool }: | ||
if e.Temporary() { | ||
return true | ||
} | ||
} | ||
// HTTP 429, 502, 503, and 504 all map to gRPC UNAVAILABLE per | ||
// https://grpc.github.io/grpc/core/md_doc_http-grpc-status-mapping.html. | ||
// | ||
// This is only necessary for the experimental gRPC-based media operations. | ||
if st, ok := status.FromError(err); ok && st.Code() == codes.Unavailable { | ||
return true | ||
} | ||
// Unwrap is only supported in go1.13.x+ | ||
if e, ok := err.(interface{ Unwrap() error }); ok { | ||
return defaultShouldRetry(e.Unwrap()) | ||
} | ||
return false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters