diff --git a/physical/dynamodb.go b/physical/dynamodb.go index 4c7cefbfe968..08d96648023b 100644 --- a/physical/dynamodb.go +++ b/physical/dynamodb.go @@ -317,11 +317,11 @@ func (d *DynamoDBBackend) Delete(key string) error { prefixes := prefixes(key) sort.Sort(sort.Reverse(sort.StringSlice(prefixes))) for _, prefix := range prefixes { - items, err := d.List(prefix) + hasChildren, err := d.hasChildren(prefix) if err != nil { return err } - if len(items) == 1 { + if !hasChildren { requests = append(requests, &dynamodb.WriteRequest{ DeleteRequest: &dynamodb.DeleteRequest{ Key: map[string]*dynamodb.AttributeValue{ @@ -378,6 +378,36 @@ func (d *DynamoDBBackend) List(prefix string) ([]string, error) { return keys, nil } +func (d *DynamoDBBackend) hasChildren(prefix string) (bool, error) { + defer metrics.MeasureSince([]string{"dynamodb", "list"}, time.Now()) + + prefix = strings.TrimSuffix(prefix, "/") + + prefix = escapeEmptyPath(prefix) + queryInput := &dynamodb.QueryInput{ + TableName: aws.String(d.table), + ConsistentRead: aws.Bool(true), + KeyConditions: map[string]*dynamodb.Condition{ + "Path": { + ComparisonOperator: aws.String("EQ"), + AttributeValueList: []*dynamodb.AttributeValue{{ + S: aws.String(prefix), + }}, + }, + }, + Limit: aws.Int64(2), + } + + d.permitPool.Acquire() + defer d.permitPool.Release() + + out, err := d.client.Query(queryInput) + if err != nil { + return false, err + } + return len(out.Items) > 1, nil +} + // LockWith is used for mutual exclusion based on the given key. func (d *DynamoDBBackend) LockWith(key, value string) (Lock, error) { identity, err := uuid.GenerateUUID()