Merge pull request #2879 from bblommers/feature/dynamodb_transact_write_items
Feature: DynamoDB: transact_write_items
This commit is contained in:
commit
2b255b0c5b
3 changed files with 459 additions and 7 deletions
|
|
@ -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"):
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue