Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dynamodb - Support backing off a bit when throttling / limit-exceeded exceptions happen #2462

Merged
merged 2 commits into from
Jun 25, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 38 additions & 7 deletions builtin/providers/aws/resource_aws_dynamodb_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,20 @@ import (
"github.com/hashicorp/terraform/helper/schema"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/dynamodb"
"github.com/hashicorp/terraform/helper/hashcode"
)

// Number of times to retry if a throttling-related exception occurs
const DYNAMODB_MAX_THROTTLE_RETRIES = 5

// How long to sleep when a throttle-event happens
const DYNAMODB_THROTTLE_SLEEP = 5 * time.Second

// How long to sleep if a limit-exceeded event happens
const DYNAMODB_LIMIT_EXCEEDED_SLEEP = 10 * time.Second

// A number of these are marked as computed because if you don't
// provide a value, DynamoDB will provide you with defaults (which are the
// default values specified below)
Expand Down Expand Up @@ -249,15 +259,36 @@ func resourceAwsDynamoDbTableCreate(d *schema.ResourceData, meta interface{}) er
req.GlobalSecondaryIndexes = globalSecondaryIndexes
}

output, err := dynamodbconn.CreateTable(req)
if err != nil {
return fmt.Errorf("Error creating DynamoDB table: %s", err)
attemptCount := 1
for attemptCount <= DYNAMODB_MAX_THROTTLE_RETRIES {
output, err := dynamodbconn.CreateTable(req)
if err != nil {
if awsErr, ok := err.(awserr.Error); ok {
if awsErr.Code() == "ThrottlingException" {
log.Printf("[DEBUG] Attempt %d/%d: Sleeping for a bit to throttle back create request", attemptCount, DYNAMODB_MAX_THROTTLE_RETRIES)
time.Sleep(DYNAMODB_THROTTLE_SLEEP)
attemptCount += 1
} else if awsErr.Code() == "LimitExceededException" {
log.Printf("[DEBUG] Limit on concurrent table creations hit, sleeping for a bit")
time.Sleep(DYNAMODB_LIMIT_EXCEEDED_SLEEP)
attemptCount += 1
} else {
// Some other non-retryable exception occurred
return fmt.Errorf("AWS Error creating DynamoDB table: %s", err)
}
} else {
// Non-AWS exception occurred, give up
return fmt.Errorf("Error creating DynamoDB table: %s", err)
}
} else {
// No error, set ID and return
d.SetId(*output.TableDescription.TableName)
return nil
}
}

d.SetId(*output.TableDescription.TableName)

// Creation complete, nothing to re-read
return nil
// Too many throttling events occurred, give up
return fmt.Errorf("Unable to create DynamoDB table '%s' after %d attempts", name, attemptCount)
}

func resourceAwsDynamoDbTableUpdate(d *schema.ResourceData, meta interface{}) error {
Expand Down