From 8f1d408c5234849dff3a5dfa0c014952a8c6d29e Mon Sep 17 00:00:00 2001 From: Harlow Ward Date: Sat, 30 Apr 2016 16:20:01 -0700 Subject: [PATCH] Fix recoverable error tests --- awsbackoff.go | 81 +------------------------ errors.go | 64 +++++++++++++++++++ awsbackoff_test.go.bk => errors_test.go | 13 ++-- 3 files changed, 71 insertions(+), 87 deletions(-) create mode 100644 errors.go rename awsbackoff_test.go.bk => errors_test.go (50%) diff --git a/awsbackoff.go b/awsbackoff.go index 79e544b..bf3a964 100644 --- a/awsbackoff.go +++ b/awsbackoff.go @@ -2,36 +2,11 @@ package connector import ( "math" - "net" - "net/url" - "regexp" "time" - - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/lib/pq" ) -type isRecoverableErrorFunc func(error) bool - -var isRecoverableErrors = []isRecoverableErrorFunc{ - kinesisIsRecoverableError, - netIsRecoverableError, - redshiftIsRecoverableError, - urlIsRecoverableError, -} - -// isRecoverableError determines whether the error is recoverable -func isRecoverableError(err error) bool { - for _, errF := range isRecoverableErrors { - if errF(err) { - return true - } - } - return false -} - -// handle the aws exponential backoff -// wait up to 5 minutes based on the aws exponential backoff algorithm +// AWS Exponential Backoff +// Wait up to 5 minutes based on the aws exponential backoff algorithm // http://docs.aws.amazon.com/general/latest/gr/api-retries.html func handleAwsWaitTimeExp(attempts int) { if attempts > 0 { @@ -39,55 +14,3 @@ func handleAwsWaitTimeExp(attempts int) { time.Sleep(waitTime) } } - -func kinesisIsRecoverableError(err error) bool { - recoverableErrorCodes := map[string]bool{ - "InternalFailure": true, - "ProvisionedThroughputExceededException": true, - "RequestError": true, - "ServiceUnavailable": true, - "Throttling": true, - } - - if err, ok := err.(awserr.Error); ok { - if ok && recoverableErrorCodes[err.Code()] == true { - return true - } - } - - return false -} - -func urlIsRecoverableError(err error) bool { - _, ok := err.(*url.Error) - if ok { - return true - } - return false -} - -func netIsRecoverableError(err error) bool { - recoverableErrors := map[string]bool{ - "connection reset by peer": true, - } - cErr, ok := err.(*net.OpError) - if ok && recoverableErrors[cErr.Err.Error()] == true { - return true - } - return false -} - -func redshiftIsRecoverableError(err error) bool { - redshiftRecoverableErrors := []*regexp.Regexp{ - regexp.MustCompile("The specified S3 prefix '.*?' does not exist"), - } - - if cErr, ok := err.(pq.Error); ok { - for _, re := range redshiftRecoverableErrors { - if re.MatchString(cErr.Message) { - return true - } - } - } - return false -} diff --git a/errors.go b/errors.go new file mode 100644 index 0000000..d31aa39 --- /dev/null +++ b/errors.go @@ -0,0 +1,64 @@ +package connector + +import ( + "net" + "net/url" + + "github.com/aws/aws-sdk-go/aws/awserr" +) + +type isRecoverableErrorFunc func(error) bool + +var isRecoverableErrors = []isRecoverableErrorFunc{ + kinesisIsRecoverableError, + netIsRecoverableError, + urlIsRecoverableError, +} + +// isRecoverableError determines whether the error is recoverable +func isRecoverableError(err error) bool { + for _, errF := range isRecoverableErrors { + if errF(err) { + return true + } + } + + return false +} + +func kinesisIsRecoverableError(err error) bool { + recoverableErrorCodes := map[string]bool{ + "InternalFailure": true, + "ProvisionedThroughputExceededException": true, + "RequestError": true, + "ServiceUnavailable": true, + "Throttling": true, + } + + if err, ok := err.(awserr.Error); ok { + if ok && recoverableErrorCodes[err.Code()] == true { + return true + } + } + + return false +} + +func urlIsRecoverableError(err error) bool { + _, ok := err.(*url.Error) + if ok { + return true + } + return false +} + +func netIsRecoverableError(err error) bool { + recoverableErrors := map[string]bool{ + "connection reset by peer": true, + } + cErr, ok := err.(*net.OpError) + if ok && recoverableErrors[cErr.Err.Error()] == true { + return true + } + return false +} diff --git a/awsbackoff_test.go.bk b/errors_test.go similarity index 50% rename from awsbackoff_test.go.bk rename to errors_test.go index af3360e..06be6c1 100644 --- a/awsbackoff_test.go.bk +++ b/errors_test.go @@ -5,9 +5,8 @@ import ( "net" "testing" + "github.com/aws/aws-sdk-go/aws/awserr" "github.com/bmizerany/assert" - "github.com/lib/pq" - "github.com/sendgridlabs/go-kinesis" ) func Test_isRecoverableError(t *testing.T) { @@ -15,15 +14,13 @@ func Test_isRecoverableError(t *testing.T) { err error isRecoverable bool }{ - {err: &kinesis.Error{Code: "ProvisionedThroughputExceededException"}, isRecoverable: true}, - {err: &kinesis.Error{Code: "Throttling"}, isRecoverable: true}, - {err: &kinesis.Error{Code: "ServiceUnavailable"}, isRecoverable: true}, - {err: &kinesis.Error{Code: "ExpiredIteratorException"}, isRecoverable: false}, + {err: awserr.New("ProvisionedThroughputExceededException", "", nil), isRecoverable: true}, + {err: awserr.New("Throttling", "", nil), isRecoverable: true}, + {err: awserr.New("ServiceUnavailable", "", nil), isRecoverable: true}, + {err: awserr.New("ExpiredIteratorException", "", nil), isRecoverable: false}, {err: &net.OpError{Err: fmt.Errorf("connection reset by peer")}, isRecoverable: true}, {err: &net.OpError{Err: fmt.Errorf("unexpected error")}, isRecoverable: false}, {err: fmt.Errorf("an arbitrary error"), isRecoverable: false}, - {err: pq.Error{Message: "The specified S3 prefix 'somefilethatismissing' does not exist"}, isRecoverable: true}, - {err: pq.Error{Message: "Some other pq error"}, isRecoverable: false}, } for _, tc := range testCases {