Merge pull request #2879 from bblommers/feature/dynamodb_transact_write_items

Feature: DynamoDB: transact_write_items
This commit is contained in:
Steve Pulec 2020-04-26 15:20:19 -05:00 committed by GitHub
commit 2b255b0c5b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 459 additions and 7 deletions

View file

@ -1209,9 +1209,9 @@ class DynamoDBBackend(BaseBackend):
table_name,
key,
update_expression,
attribute_updates,
expression_attribute_names,
expression_attribute_values,
attribute_updates=None,
expected=None,
condition_expression=None,
):
@ -1332,6 +1332,94 @@ class DynamoDBBackend(BaseBackend):
return table.ttl
def transact_write_items(self, transact_items):
# Create a backup in case any of the transactions fail
original_table_state = copy.deepcopy(self.tables)
try:
for item in transact_items:
if "ConditionCheck" in item:
item = item["ConditionCheck"]
key = item["Key"]
table_name = item["TableName"]
condition_expression = item.get("ConditionExpression", None)
expression_attribute_names = item.get(
"ExpressionAttributeNames", None
)
expression_attribute_values = item.get(
"ExpressionAttributeValues", None
)
current = self.get_item(table_name, key)
condition_op = get_filter_expression(
condition_expression,
expression_attribute_names,
expression_attribute_values,
)
if not condition_op.expr(current):
raise ValueError("The conditional request failed")
elif "Put" in item:
item = item["Put"]
attrs = item["Item"]
table_name = item["TableName"]
condition_expression = item.get("ConditionExpression", None)
expression_attribute_names = item.get(
"ExpressionAttributeNames", None
)
expression_attribute_values = item.get(
"ExpressionAttributeValues", None
)
self.put_item(
table_name,
attrs,
condition_expression=condition_expression,
expression_attribute_names=expression_attribute_names,
expression_attribute_values=expression_attribute_values,
)
elif "Delete" in item:
item = item["Delete"]
key = item["Key"]
table_name = item["TableName"]
condition_expression = item.get("ConditionExpression", None)
expression_attribute_names = item.get(
"ExpressionAttributeNames", None
)
expression_attribute_values = item.get(
"ExpressionAttributeValues", None
)
self.delete_item(
table_name,
key,
condition_expression=condition_expression,
expression_attribute_names=expression_attribute_names,
expression_attribute_values=expression_attribute_values,
)
elif "Update" in item:
item = item["Update"]
key = item["Key"]
table_name = item["TableName"]
update_expression = item["UpdateExpression"]
condition_expression = item.get("ConditionExpression", None)
expression_attribute_names = item.get(
"ExpressionAttributeNames", None
)
expression_attribute_values = item.get(
"ExpressionAttributeValues", None
)
self.update_item(
table_name,
key,
update_expression=update_expression,
condition_expression=condition_expression,
expression_attribute_names=expression_attribute_names,
expression_attribute_values=expression_attribute_values,
)
else:
raise ValueError
except: # noqa: E722 Do not use bare except
# Rollback to the original state, and reraise the error
self.tables = original_table_state
raise
dynamodb_backends = {}
for region in Session().get_available_regions("dynamodb"):

View file

@ -762,12 +762,12 @@ class DynamoHandler(BaseResponse):
item = self.dynamodb_backend.update_item(
name,
key,
update_expression,
attribute_updates,
expression_attribute_names,
expression_attribute_values,
expected,
condition_expression,
update_expression=update_expression,
attribute_updates=attribute_updates,
expression_attribute_names=expression_attribute_names,
expression_attribute_values=expression_attribute_values,
expected=expected,
condition_expression=condition_expression,
)
except MockValidationException as mve:
er = "com.amazonaws.dynamodb.v20111205#ValidationException"
@ -924,3 +924,15 @@ class DynamoHandler(BaseResponse):
result.update({"ConsumedCapacity": [v for v in consumed_capacity.values()]})
return dynamo_json_dump(result)
def transact_write_items(self):
transact_items = self.body["TransactItems"]
try:
self.dynamodb_backend.transact_write_items(transact_items)
except ValueError:
er = "com.amazonaws.dynamodb.v20111205#ConditionalCheckFailedException"
return self.error(
er, "A condition specified in the operation could not be evaluated."
)
response = {"ConsumedCapacity": [], "ItemCollectionMetrics": {}}
return dynamo_json_dump(response)