Skip to content

Commit 9023cbf

Browse files
authored
Merge pull request #37 from Clever/dynamo-add-retries
Add retries during DynamoDB bucket intialization
2 parents d6df64f + 6fcd44a commit 9023cbf

File tree

4 files changed

+44
-5
lines changed

4 files changed

+44
-5
lines changed

Gopkg.lock

+9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Gopkg.toml

+4
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,7 @@
55
[[constraint]]
66
name = "github.com/aws/aws-sdk-go"
77
version = "1.29.0"
8+
9+
[[constraint]]
10+
name = "github.com/eapache/go-resiliency"
11+
version = "^1.2.0"

VERSION

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
v1.0.0
1+
v1.1.0
2+
- v1.1.0: add retries during dynamodb bucket initialization
23
- v1.0.0: added dynamodb backed implementation

dynamodb/bucket.go

+29-4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ For additional details please refer to: https://github.com/Clever/leakybucket/tr
66
package dynamodb
77

88
import (
9+
"strings"
910
"sync"
1011
"time"
1112

@@ -14,6 +15,7 @@ import (
1415
"github.com/aws/aws-sdk-go/aws"
1516
"github.com/aws/aws-sdk-go/aws/session"
1617
"github.com/aws/aws-sdk-go/service/dynamodb"
18+
"github.com/eapache/go-resiliency/retrier"
1719
)
1820

1921
var _ leakybucket.Bucket = &bucket{}
@@ -132,10 +134,16 @@ func New(tableName string, s *session.Session, itemTTL time.Duration) (*Storage,
132134
ttl: itemTTL,
133135
}
134136

135-
// fail early if the table doesn't exist or we have any other issues with the DynamoDB API
136-
if _, err := ddb.DescribeTable(&dynamodb.DescribeTableInput{
137-
TableName: aws.String(tableName),
138-
}); err != nil {
137+
// Fail early if the table doesn't exist or we have any other issues with the DynamoDB API
138+
// but guarantee we retry dial timeouts to be tolerant to a networking blip
139+
r := retrier.New(retrier.ExponentialBackoff(5, 1*time.Second), dialTimeoutRetrier{})
140+
err := r.Run(func() error {
141+
_, err := ddb.DescribeTable(&dynamodb.DescribeTableInput{
142+
TableName: aws.String(tableName),
143+
})
144+
return err
145+
})
146+
if err != nil {
139147
return nil, err
140148
}
141149

@@ -157,3 +165,20 @@ func min(a, b uint) uint {
157165
}
158166
return b
159167
}
168+
169+
// dialTimeoutRetrier classifies errors from DynamoDB API in the form of
170+
// Post https://dynamodb.{region}.amazonaws.com: dial tcp x.x.x.x: i/o timeout
171+
// as retryable errors. This classifier is only used in `New` as we don't want to override the
172+
// consumer's configuration during normal operation
173+
type dialTimeoutRetrier struct{}
174+
175+
var _ retrier.Classifier = dialTimeoutRetrier{}
176+
177+
func (dialTimeoutRetrier) Classify(err error) retrier.Action {
178+
if err == nil {
179+
return retrier.Succeed
180+
} else if strings.Contains(err.Error(), "dial tcp") && strings.Contains(err.Error(), "i/o timeout") {
181+
return retrier.Retry
182+
}
183+
return retrier.Fail
184+
}

0 commit comments

Comments
 (0)