diff --git a/cluster_analyticsquery.go b/cluster_analyticsquery.go index c22f3845..f89218c8 100644 --- a/cluster_analyticsquery.go +++ b/cluster_analyticsquery.go @@ -390,7 +390,7 @@ func (c *Cluster) analyticsQuery(ctx context.Context, traceCtx opentracing.SpanC break } - if !isRetryableError(err) || c.sb.AnalyticsRetryBehavior == nil || !c.sb.AnalyticsRetryBehavior.CanRetry(retries) { + if !IsRetryableError(err) || c.sb.AnalyticsRetryBehavior == nil || !c.sb.AnalyticsRetryBehavior.CanRetry(retries) { break } diff --git a/cluster_query.go b/cluster_query.go index 035474f3..3f31ffc6 100644 --- a/cluster_query.go +++ b/cluster_query.go @@ -383,7 +383,7 @@ func (c *Cluster) query(ctx context.Context, traceCtx opentracing.SpanContext, s break } - if !isRetryableError(err) || c.sb.N1qlRetryBehavior == nil || !c.sb.N1qlRetryBehavior.CanRetry(retries) { + if !IsRetryableError(err) || c.sb.N1qlRetryBehavior == nil || !c.sb.N1qlRetryBehavior.CanRetry(retries) { break } @@ -432,7 +432,7 @@ func (c *Cluster) doPreparedN1qlQuery(ctx context.Context, traceCtx opentracing. // If we get error 4050, 4070 or 5000, we should attempt // to re-prepare the statement immediately before failing. - if !isRetryableError(err) { + if !IsRetryableError(err) { return nil, err } } diff --git a/cluster_searchquery.go b/cluster_searchquery.go index 8c25a669..8ae25431 100644 --- a/cluster_searchquery.go +++ b/cluster_searchquery.go @@ -497,7 +497,7 @@ func (c *Cluster) searchQuery(ctx context.Context, traceCtx opentracing.SpanCont break } - if !isRetryableError(err) || c.sb.SearchRetryBehavior == nil || !c.sb.SearchRetryBehavior.CanRetry(retries) { + if !IsRetryableError(err) || c.sb.SearchRetryBehavior == nil || !c.sb.SearchRetryBehavior.CanRetry(retries) { break } diff --git a/error.go b/error.go index 4421ce7f..eac525bc 100644 --- a/error.go +++ b/error.go @@ -105,6 +105,10 @@ func (err kvError) DurabilityError() bool { err.StatusCode() == int(gocbcore.StatusDurabilityInvalidLevel) } +func (err kvError) retryable() bool { + return err.TemporaryFailureError() +} + // DurabilityError occurs when an error occurs during performing durability operations. type DurabilityError interface { DurabilityError() bool @@ -195,6 +199,16 @@ func IsTimeoutError(err error) bool { } } +// IsRetryableError indicates that the operation should be retried. +func IsRetryableError(err error) bool { + switch errType := errors.Cause(err).(type) { + case retryAbleError: + return errType.retryable() + default: + return false + } +} + // KV Specific Errors // IsKeyValueError verifies whether or not the cause for an error is a KeyValueError. @@ -889,15 +903,6 @@ func (e noResultsError) NoResultsError() bool { return true } -func isRetryableError(err error) bool { - switch errType := errors.Cause(err).(type) { - case retryAbleError: - return errType.retryable() - default: - return false - } -} - func maybeEnhanceKVErr(err error, key string, isInsertOp bool) error { cause := errors.Cause(err) diff --git a/error_test.go b/error_test.go index 78569fa8..c307a80d 100644 --- a/error_test.go +++ b/error_test.go @@ -30,3 +30,41 @@ func TestIsCasMismatchError(t *testing.T) { t.Fatalf("Error should not have been cas mismatch") } } + +func TestKVIsRetryable(t *testing.T) { + err := &gocbcore.KvError{ + Code: gocbcore.StatusTmpFail, + } + + enhancedErr := maybeEnhanceKVErr(err, "myfakekey", false) + if !IsRetryableError(enhancedErr) { + t.Fatalf("StatusTmpFail error should have been retryable") + } + + err = &gocbcore.KvError{ + Code: gocbcore.StatusOutOfMemory, + } + + enhancedErr = maybeEnhanceKVErr(err, "myfakekey", false) + if !IsRetryableError(enhancedErr) { + t.Fatalf("StatusOutOfMemory error should have been retryable") + } + + err = &gocbcore.KvError{ + Code: gocbcore.StatusBusy, + } + + enhancedErr = maybeEnhanceKVErr(err, "myfakekey", false) + if !IsRetryableError(enhancedErr) { + t.Fatalf("StatusBusy error should have been retryable") + } + + err = &gocbcore.KvError{ + Code: gocbcore.StatusTooBig, + } + + enhancedErr = maybeEnhanceKVErr(err, "myfakekey", false) + if IsRetryableError(enhancedErr) { + t.Fatalf("StatusTooBig error should not have been retryable") + } +}