aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/cloud.google.com/go/internal/retry.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/cloud.google.com/go/internal/retry.go')
-rw-r--r--vendor/cloud.google.com/go/internal/retry.go37
1 files changed, 34 insertions, 3 deletions
diff --git a/vendor/cloud.google.com/go/internal/retry.go b/vendor/cloud.google.com/go/internal/retry.go
index 7a7b4c205..2943a6d0b 100644
--- a/vendor/cloud.google.com/go/internal/retry.go
+++ b/vendor/cloud.google.com/go/internal/retry.go
@@ -16,9 +16,11 @@ package internal
import (
"context"
+ "fmt"
"time"
gax "github.com/googleapis/gax-go/v2"
+ "google.golang.org/grpc/status"
)
// Retry calls the supplied function f repeatedly according to the provided
@@ -44,11 +46,40 @@ func retry(ctx context.Context, bo gax.Backoff, f func() (stop bool, err error),
lastErr = err
}
p := bo.Pause()
- if cerr := sleep(ctx, p); cerr != nil {
+ if ctxErr := sleep(ctx, p); ctxErr != nil {
if lastErr != nil {
- return Annotatef(lastErr, "retry failed with %v; last error", cerr)
+ return wrappedCallErr{ctxErr: ctxErr, wrappedErr: lastErr}
}
- return cerr
+ return ctxErr
}
}
}
+
+// Use this error type to return an error which allows introspection of both
+// the context error and the error from the service.
+type wrappedCallErr struct {
+ ctxErr error
+ wrappedErr error
+}
+
+func (e wrappedCallErr) Error() string {
+ return fmt.Sprintf("retry failed with %v; last error: %v", e.ctxErr, e.wrappedErr)
+}
+
+func (e wrappedCallErr) Unwrap() error {
+ return e.wrappedErr
+}
+
+// Is allows errors.Is to match the error from the call as well as context
+// sentinel errors.
+func (e wrappedCallErr) Is(err error) bool {
+ return e.ctxErr == err || e.wrappedErr == err
+}
+
+// GRPCStatus allows the wrapped error to be used with status.FromError.
+func (e wrappedCallErr) GRPCStatus() *status.Status {
+ if s, ok := status.FromError(e.wrappedErr); ok {
+ return s
+ }
+ return nil
+}