@@ -10,7 +10,10 @@ package changefeedccl
1010
1111import (
1212 "fmt"
13+ "reflect"
1314 "strings"
15+
16+ "github.com/cockroachdb/errors"
1417)
1518
1619const retryableErrorString = "retryable changefeed error"
@@ -40,40 +43,46 @@ func (e *retryableError) Unwrap() error { return e.wrapped }
4043// IsRetryableError returns true if the supplied error, or any of its parent
4144// causes, is a IsRetryableError.
4245func IsRetryableError (err error ) bool {
43- for {
44- if err == nil {
45- return false
46- }
47- if _ , ok := err .(* retryableError ); ok {
48- return true
49- }
50- errStr := err .Error ()
51- if strings .Contains (errStr , retryableErrorString ) {
52- // If a RetryableError occurs on a remote node, DistSQL serializes it such
53- // that we can't recover the structure and we have to rely on this
54- // unfortunate string comparison.
55- return true
56- }
57- if strings .Contains (errStr , `rpc error` ) {
58- // When a crdb node dies, any DistSQL flows with processors scheduled on
59- // it get an error with "rpc error" in the message from the call to
60- // `(*DistSQLPlanner).Run`.
61- return true
62- }
63- if e , ok := err .(interface { Unwrap () error }); ok {
64- err = e .Unwrap ()
65- continue
66- }
46+ if err == nil {
6747 return false
6848 }
49+ if errors .HasType (err , (* retryableError )(nil )) {
50+ return true
51+ }
52+
53+ // TODO(knz): this is a bad implementation. Make it go away
54+ // by avoiding string comparisons.
55+
56+ errStr := err .Error ()
57+ if strings .Contains (errStr , retryableErrorString ) {
58+ // If a RetryableError occurs on a remote node, DistSQL serializes it such
59+ // that we can't recover the structure and we have to rely on this
60+ // unfortunate string comparison.
61+ return true
62+ }
63+ if strings .Contains (errStr , `rpc error` ) {
64+ // When a crdb node dies, any DistSQL flows with processors scheduled on
65+ // it get an error with "rpc error" in the message from the call to
66+ // `(*DistSQLPlanner).Run`.
67+ return true
68+ }
69+ return false
6970}
7071
7172// MaybeStripRetryableErrorMarker performs some minimal attempt to clean the
7273// RetryableError marker out. This won't do anything if the RetryableError
7374// itself has been wrapped, but that's okay, we'll just have an uglier string.
7475func MaybeStripRetryableErrorMarker (err error ) error {
75- if e , ok := err .(* retryableError ); ok {
76- err = e .wrapped
76+ // The following is a hack to work around the error cast linter.
77+ // What we're doing here is really not kosher; this function
78+ // has no business in assuming that the retryableError{} wrapper
79+ // has not been wrapped already. We could even expect that
80+ // it gets wrapped in the common case.
81+ // TODO(knz): Remove/replace this.
82+ if reflect .TypeOf (err ) == retryableErrorType {
83+ err = errors .UnwrapOnce (err )
7784 }
7885 return err
7986}
87+
88+ var retryableErrorType = reflect .TypeOf ((* retryableError )(nil ))
0 commit comments