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

This commit is contained in:
John Ewart 2015-06-24 07:23:16 -07:00
parent cddd54c3de
commit 7718cd194c
1 changed files with 37 additions and 7 deletions

View File

@ -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)
@ -249,15 +259,35 @@ 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 creation hit, sleeping for a bit")
time.Sleep(DYNAMODB_LIMIT_EXCEEDED_SLEEP)
} 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 {