From 8c3100ec2edf6bc401b440bb267d7e7aaf778e1b Mon Sep 17 00:00:00 2001 From: Chris Perez Date: Mon, 9 Sep 2024 12:03:20 -0600 Subject: [PATCH 01/18] Add ExecuteStatement in DynamoDbLowLevelContext --- .../DynamoDbLowLevelContext.cs | 12 ++- .../IDynamoDbLowLevelContext.cs | 5 +- .../ExecuteStatementRequestHttpContent.cs | 57 ++++++++++++ .../ExecuteStatementResponseParser.cs | 31 +++++++ .../ExecuteStatementRequest.cs | 83 ++++++++++++++++++ .../ExecuteStatementResponse.cs | 86 +++++++++++++++++++ 6 files changed, 272 insertions(+), 2 deletions(-) create mode 100644 src/EfficientDynamoDb/Internal/Operations/ExecuteStatement/ExecuteStatementRequestHttpContent.cs create mode 100644 src/EfficientDynamoDb/Internal/Operations/ExecuteStatement/ExecuteStatementResponseParser.cs create mode 100644 src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementRequest.cs create mode 100644 src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementResponse.cs diff --git a/src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelContext.cs b/src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelContext.cs index 416b139b..b9582728 100644 --- a/src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelContext.cs +++ b/src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelContext.cs @@ -11,6 +11,7 @@ using EfficientDynamoDb.Internal.Operations.BatchWriteItem; using EfficientDynamoDb.Internal.Operations.DeleteItem; using EfficientDynamoDb.Internal.Operations.DescribeTable; +using EfficientDynamoDb.Internal.Operations.ExecuteStatement; using EfficientDynamoDb.Internal.Operations.GetItem; using EfficientDynamoDb.Internal.Operations.PutItem; using EfficientDynamoDb.Internal.Operations.Query; @@ -24,6 +25,7 @@ using EfficientDynamoDb.Operations.DeleteItem; using EfficientDynamoDb.Operations.DescribeTable; using EfficientDynamoDb.Operations.DescribeTable.Models.Enums; +using EfficientDynamoDb.Operations.ExecuteStatement; using EfficientDynamoDb.Operations.GetItem; using EfficientDynamoDb.Operations.PutItem; using EfficientDynamoDb.Operations.Query; @@ -145,7 +147,15 @@ public async Task TransactWriteItemsAsync(TransactWr return TransactWriteItemsResponseParser.Parse(result); } - + + public async Task ExecuteStatementAsync(ExecuteStatementRequest request, CancellationToken cancellationToken = default) + { + var httpContent = new ExecuteStatementRequestHttpContent(request); + using var response = await Api.SendAsync(Config, httpContent, cancellationToken).ConfigureAwait(false); + var result = await ReadDocumentAsync(response, QueryParsingOptions.Instance, cancellationToken).ConfigureAwait(false); + return ExecuteStatementResponseParser.Parse(result!); + } + public T ToObject(Document document) where T : class => document.ToObject(Config.Metadata); public Document ToDocument(T entity) where T : class => entity.ToDocument(Config.Metadata); diff --git a/src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelContext.cs b/src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelContext.cs index c729c1bf..e6a7fbc0 100644 --- a/src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelContext.cs +++ b/src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelContext.cs @@ -4,6 +4,7 @@ using EfficientDynamoDb.Operations.BatchGetItem; using EfficientDynamoDb.Operations.BatchWriteItem; using EfficientDynamoDb.Operations.DeleteItem; +using EfficientDynamoDb.Operations.ExecuteStatement; using EfficientDynamoDb.Operations.GetItem; using EfficientDynamoDb.Operations.PutItem; using EfficientDynamoDb.Operations.Query; @@ -35,7 +36,9 @@ public interface IDynamoDbLowLevelContext Task DeleteItemAsync(DeleteItemRequest request, CancellationToken cancellationToken = default); Task TransactWriteItemsAsync(TransactWriteItemsRequest request, CancellationToken cancellationToken = default); - + + Task ExecuteStatementAsync(ExecuteStatementRequest request, CancellationToken cancellationToken = default); + T ToObject(Document document) where T : class; Document ToDocument(T entity) where T : class; diff --git a/src/EfficientDynamoDb/Internal/Operations/ExecuteStatement/ExecuteStatementRequestHttpContent.cs b/src/EfficientDynamoDb/Internal/Operations/ExecuteStatement/ExecuteStatementRequestHttpContent.cs new file mode 100644 index 00000000..264997d7 --- /dev/null +++ b/src/EfficientDynamoDb/Internal/Operations/ExecuteStatement/ExecuteStatementRequestHttpContent.cs @@ -0,0 +1,57 @@ +using EfficientDynamoDb.Converters; +using EfficientDynamoDb.Internal.Extensions; +using EfficientDynamoDb.Internal.Operations.Shared; +using EfficientDynamoDb.Operations.ExecuteStatement; +using EfficientDynamoDb.Operations.Shared; +using System.Threading.Tasks; + +namespace EfficientDynamoDb.Internal.Operations.ExecuteStatement +{ + internal class ExecuteStatementRequestHttpContent : DynamoDbHttpContent + { + private readonly ExecuteStatementRequest _request; + + public ExecuteStatementRequestHttpContent(ExecuteStatementRequest executeStatementRequest) : base("DynamoDB_20120810.ExecuteStatement") + { + _request = executeStatementRequest; + } + + protected override ValueTask WriteDataAsync(DdbWriter writer) + { + var json = writer.JsonWriter; + json.WriteStartObject(); + + json.WritePropertyName("Statement"); + json.WriteStringValue(_request.Statement); + + json.WritePropertyName("Parameters"); + json.WriteStartArray(); + foreach (var parameter in _request.Parameters) + { + parameter.Write(json); + } + json.WriteEndArray(); + + json.WritePropertyName("ConsistentRead"); + json.WriteBooleanValue(_request.ConsistentRead); + + if (_request.Limit > 0) + { + json.WritePropertyName("Limit"); + json.WriteNumberValue(_request.Limit); + } + + if (_request.ReturnConsumedCapacity != ReturnConsumedCapacity.None) + json.WriteReturnConsumedCapacity(_request.ReturnConsumedCapacity); + + if (_request.ReturnItemCollectionMetrics != ReturnItemCollectionMetrics.None) + json.WriteReturnItemCollectionMetrics(_request.ReturnItemCollectionMetrics); + + if (_request.ReturnValuesOnConditionCheckFailure != ReturnValuesOnConditionCheckFailure.None) + json.WriteReturnValuesOnConditionCheckFailure(_request.ReturnValuesOnConditionCheckFailure); + + json.WriteEndObject(); + return default; + } + } +} diff --git a/src/EfficientDynamoDb/Internal/Operations/ExecuteStatement/ExecuteStatementResponseParser.cs b/src/EfficientDynamoDb/Internal/Operations/ExecuteStatement/ExecuteStatementResponseParser.cs new file mode 100644 index 00000000..a89eb7e9 --- /dev/null +++ b/src/EfficientDynamoDb/Internal/Operations/ExecuteStatement/ExecuteStatementResponseParser.cs @@ -0,0 +1,31 @@ +using EfficientDynamoDb.DocumentModel; +using EfficientDynamoDb.Internal.Operations.Shared; +using EfficientDynamoDb.Operations.ExecuteStatement; +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace EfficientDynamoDb.Internal.Operations.ExecuteStatement +{ + internal static class ExecuteStatementResponseParser + { + public static ExecuteStatementResponse Parse(Document response) => + new ExecuteStatementResponse + { + Items = response.TryGetValue("Items", out var items) ? items._documentListValue.Items : Array.Empty(), + LastEvaluatedKey = ParseLastEvaluatedKey(response), + NextToken = response.TryGetValue("NextToken", out var nextToken) ? nextToken.AsString() : string.Empty, + ConsumedCapacity = CapacityParser.ParseFullConsumedCapacity(response), + }; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static IReadOnlyDictionary? ParseLastEvaluatedKey(Document response) + { + if (!response.TryGetValue("LastEvaluatedKey", out var attribute)) + return null; + + var document = attribute.AsDocument(); + return document.Count > 0 ? document : null; + } + } +} diff --git a/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementRequest.cs b/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementRequest.cs new file mode 100644 index 00000000..95e2bc59 --- /dev/null +++ b/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementRequest.cs @@ -0,0 +1,83 @@ +using EfficientDynamoDb.DocumentModel; +using EfficientDynamoDb.Operations.Shared; +using System.Collections.Generic; + +namespace EfficientDynamoDb.Operations.ExecuteStatement +{ + public class ExecuteStatementRequest + { + /// + /// Gets and sets the property Statement. + /// + /// The PartiQL statement representing the operation to run. + /// + /// + public string Statement { get; set; } = string.Empty; + + /// + /// Gets and sets the property Parameters. + /// + /// The parameters for the PartiQL statement, if any. + /// + /// + public List Parameters { get; set; } = new List(); + + /// + /// Gets and sets the property ConsistentRead. + /// + /// The consistency of a read operation. If set to true, then a strongly consistent + /// read is used; otherwise, an eventually consistent read is used. + /// + /// + public bool ConsistentRead { get; set; } + + /// + /// Gets and sets the property Limit. + /// + /// The maximum number of items to evaluate (not necessarily the number of matching items). + /// If DynamoDB processes the number of items up to the limit while processing the results, + /// it stops the operation and returns the matching values up to that point, along with + /// a key in LastEvaluatedKey to apply in a subsequent operation so you can pick + /// up where you left off. Also, if the processed dataset size exceeds 1 MB before DynamoDB + /// reaches this limit, it stops the operation and returns the matching values up to the + /// limit, and a key in LastEvaluatedKey to apply in a subsequent operation to + /// continue the operation. + /// + /// + public int Limit { get; set; } + + /// + /// Gets and sets the property NextToken. + /// + /// Set this value to get remaining results, if NextToken was returned in the statement + /// response. + /// + /// + public string NextToken { get; set; } = string.Empty; + + /// + /// Determines the level of detail about provisioned throughput consumption that is returned in the response. + /// + public ReturnConsumedCapacity ReturnConsumedCapacity { get; set; } + + /// + /// Determines whether item collection metrics are returned. + /// + public ReturnItemCollectionMetrics ReturnItemCollectionMetrics { get; set; } + + /// + /// Gets and sets the property ReturnValuesOnConditionCheckFailure. + /// + /// An optional parameter that returns the item attributes for an ExecuteStatement + /// operation that failed a condition check. + /// + /// + /// + /// There is no additional cost associated with requesting a return value aside from the + /// small network and processing overhead of receiving a larger response. No read capacity + /// units are consumed. + /// + /// + public ReturnValuesOnConditionCheckFailure ReturnValuesOnConditionCheckFailure { get; set; } + } +} diff --git a/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementResponse.cs b/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementResponse.cs new file mode 100644 index 00000000..7e9dc850 --- /dev/null +++ b/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementResponse.cs @@ -0,0 +1,86 @@ +using EfficientDynamoDb.Attributes; +using EfficientDynamoDb.DocumentModel; +using EfficientDynamoDb.Internal.Converters; +using EfficientDynamoDb.Internal.Converters.Json; +using EfficientDynamoDb.Operations.Shared.Capacity; +using EfficientDynamoDb.Operations.TransactGetItems; +using System.Collections.Generic; + +namespace EfficientDynamoDb.Operations.ExecuteStatement +{ + public class ExecuteStatementResponse + { + /// + /// Gets and sets the property Items. + /// + /// If a read operation was used, this property will contain the result of the read operation; + /// a map of attribute names and their values. For the write operations this value will + /// be empty. + /// + /// + public IReadOnlyList? Items { get; set; } + + /// + /// Gets and sets the property LastEvaluatedKey. + /// + /// The primary key of the item where the operation stopped, inclusive of the previous + /// result set. Use this value to start a new operation, excluding this value in the new + /// request. If LastEvaluatedKey is empty, then the "last page" of results has + /// been processed and there is no more data to be retrieved. If LastEvaluatedKey + /// is not empty, it does not necessarily mean that there is more data in the result set. + /// The only way to know when you have reached the end of the result set is when LastEvaluatedKey + /// is empty. + /// + /// + public IReadOnlyDictionary? LastEvaluatedKey { get; set; } + + /// + /// Gets and sets the property NextToken. + /// + /// If the response of a read request exceeds the response payload limit DynamoDB will + /// set this value in the response. If set, you can use that this value in the subsequent + /// request to get the remaining results. + /// + /// + public string NextToken { get; set; } = string.Empty; + + /// + /// The capacity units consumed by the entire ExecuteStatement operation. The values of the list are ordered according to the ordering of the request parameter. + /// + public FullConsumedCapacity? ConsumedCapacity { get; set; } + } + + public class ExecuteStatementEntityResponse + { + /// + /// An array of item attributes that match the query criteria. Each element in this array consists of an attribute name and the value for that attribute. + /// + [DynamoDbProperty("Items", typeof(JsonIReadOnlyListHintDdbConverter<>))] + public IReadOnlyList Items { get; set; } = null!; + + /// + /// The primary key of the item where the operation stopped, inclusive of the previous result set. Use this value to start a new operation, excluding this value in the new request.

+ /// If is null, then the "last page" of results has been processed and there is no more data to be retrieved.

+ /// If is not null, it does not necessarily mean that there is more data in the result set. The only way to know when you have reached the end of the result set is when is null. + ///
+ [DynamoDbProperty("LastEvaluatedKey", typeof(PaginationDdbConverter))] + public string? LastEvaluatedKey { get; set; } + + /// + /// Gets and sets the property NextToken. + /// + /// If the response of a read request exceeds the response payload limit DynamoDB will + /// set this value in the response. If set, you can use that this value in the subsequent + /// request to get the remaining results. + /// + /// + [DynamoDbProperty("NextToken")] + public string NextToken { get; set; } = string.Empty; + + /// + /// The capacity units consumed by the Query operation. The data returned includes the total provisioned throughput consumed, along with statistics for the table and any indexes involved in the operation. is only returned if the parameter was specified. + /// + [DynamoDbProperty("ConsumedCapacity", typeof(JsonObjectDdbConverter))] + public FullConsumedCapacity? ConsumedCapacity { get; set; } + } +} From 2d412a4b3904bea6492642ad2222f849d6f22e6e Mon Sep 17 00:00:00 2001 From: Chris Perez Date: Mon, 9 Sep 2024 12:04:45 -0600 Subject: [PATCH 02/18] add BatchExecuteStatement in DynamoDbLowLevelContext --- .../DynamoDbLowLevelContext.cs | 12 ++++ .../IDynamoDbLowLevelContext.cs | 4 ++ ...BatchExecuteStatementRequestHttpContent.cs | 61 ++++++++++++++++++ .../BatchExecuteStatementResponseParser.cs | 28 ++++++++ .../BatchExecuteStatementRequest.cs | 24 +++++++ .../BatchExecuteStatementResponse.cs | 64 +++++++++++++++++++ .../BatchStatementError.cs | 37 +++++++++++ .../BatchStatementErrorCodeEnum.cs | 17 +++++ .../BatchStatementRequest.cs | 48 ++++++++++++++ 9 files changed, 295 insertions(+) create mode 100644 src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementRequestHttpContent.cs create mode 100644 src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementResponseParser.cs create mode 100644 src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementRequest.cs create mode 100644 src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementResponse.cs create mode 100644 src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementError.cs create mode 100644 src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementErrorCodeEnum.cs create mode 100644 src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementRequest.cs diff --git a/src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelContext.cs b/src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelContext.cs index b9582728..63b8a227 100644 --- a/src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelContext.cs +++ b/src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelContext.cs @@ -7,11 +7,13 @@ using EfficientDynamoDb.Exceptions; using EfficientDynamoDb.Internal; using EfficientDynamoDb.Internal.Extensions; +using EfficientDynamoDb.Internal.Operations.BatchExecuteStatement; using EfficientDynamoDb.Internal.Operations.BatchGetItem; using EfficientDynamoDb.Internal.Operations.BatchWriteItem; using EfficientDynamoDb.Internal.Operations.DeleteItem; using EfficientDynamoDb.Internal.Operations.DescribeTable; using EfficientDynamoDb.Internal.Operations.ExecuteStatement; +using EfficientDynamoDb.Internal.Operations.ExecuteTransaction; using EfficientDynamoDb.Internal.Operations.GetItem; using EfficientDynamoDb.Internal.Operations.PutItem; using EfficientDynamoDb.Internal.Operations.Query; @@ -20,12 +22,14 @@ using EfficientDynamoDb.Internal.Operations.TransactWriteItems; using EfficientDynamoDb.Internal.Operations.UpdateItem; using EfficientDynamoDb.Internal.Reader; +using EfficientDynamoDb.Operations.BatchExecuteStatement; using EfficientDynamoDb.Operations.BatchGetItem; using EfficientDynamoDb.Operations.BatchWriteItem; using EfficientDynamoDb.Operations.DeleteItem; using EfficientDynamoDb.Operations.DescribeTable; using EfficientDynamoDb.Operations.DescribeTable.Models.Enums; using EfficientDynamoDb.Operations.ExecuteStatement; +using EfficientDynamoDb.Operations.ExecuteTransaction; using EfficientDynamoDb.Operations.GetItem; using EfficientDynamoDb.Operations.PutItem; using EfficientDynamoDb.Operations.Query; @@ -156,6 +160,14 @@ public async Task ExecuteStatementAsync(ExecuteStateme return ExecuteStatementResponseParser.Parse(result!); } + public async Task BatchExecuteStatementAsync(BatchExecuteStatementRequest request, CancellationToken cancellationToken = default) + { + var httpContent = new BatchExecuteStatementRequestHttpContent(request); + using var response = await Api.SendAsync(Config, httpContent, cancellationToken).ConfigureAwait(false); + var result = await ReadDocumentAsync(response, QueryParsingOptions.Instance, cancellationToken).ConfigureAwait(false); + return BatchExecuteStatementResponseParser.Parse(result!); + } + public T ToObject(Document document) where T : class => document.ToObject(Config.Metadata); public Document ToDocument(T entity) where T : class => entity.ToDocument(Config.Metadata); diff --git a/src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelContext.cs b/src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelContext.cs index e6a7fbc0..47ba8cf7 100644 --- a/src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelContext.cs +++ b/src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelContext.cs @@ -1,10 +1,12 @@ using System.Threading; using System.Threading.Tasks; using EfficientDynamoDb.DocumentModel; +using EfficientDynamoDb.Operations.BatchExecuteStatement; using EfficientDynamoDb.Operations.BatchGetItem; using EfficientDynamoDb.Operations.BatchWriteItem; using EfficientDynamoDb.Operations.DeleteItem; using EfficientDynamoDb.Operations.ExecuteStatement; +using EfficientDynamoDb.Operations.ExecuteTransaction; using EfficientDynamoDb.Operations.GetItem; using EfficientDynamoDb.Operations.PutItem; using EfficientDynamoDb.Operations.Query; @@ -39,6 +41,8 @@ public interface IDynamoDbLowLevelContext Task ExecuteStatementAsync(ExecuteStatementRequest request, CancellationToken cancellationToken = default); + Task BatchExecuteStatementAsync(BatchExecuteStatementRequest request, CancellationToken cancellationToken = default); + T ToObject(Document document) where T : class; Document ToDocument(T entity) where T : class; diff --git a/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementRequestHttpContent.cs b/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementRequestHttpContent.cs new file mode 100644 index 00000000..f97053b4 --- /dev/null +++ b/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementRequestHttpContent.cs @@ -0,0 +1,61 @@ +using EfficientDynamoDb.Converters; +using EfficientDynamoDb.Internal.Extensions; +using EfficientDynamoDb.Internal.Operations.Shared; +using EfficientDynamoDb.Operations.BatchExecuteStatement; +using EfficientDynamoDb.Operations.Shared; +using System.Text; +using System; +using System.Threading.Tasks; + +namespace EfficientDynamoDb.Internal.Operations.BatchExecuteStatement +{ + internal class BatchExecuteStatementRequestHttpContent : DynamoDbHttpContent + { + private readonly BatchExecuteStatementRequest _request; + + public BatchExecuteStatementRequestHttpContent(BatchExecuteStatementRequest request) : base("DynamoDB_20120810.BatchExecuteStatement") + { + _request = request; + } + + protected override ValueTask WriteDataAsync(DdbWriter writer) + { + var json = writer.JsonWriter; + json.WriteStartObject(); + + json.WritePropertyName("Statements"); + json.WriteStartArray(); + foreach (var statementRequest in _request.Statements) + { + json.WriteStartObject(); + + json.WritePropertyName("Statement"); + json.WriteStringValue(statementRequest.Statement); + + json.WritePropertyName("Parameters"); + json.WriteStartArray(); + foreach (var parameter in statementRequest.Parameters) + { + parameter.Write(json); + } + json.WriteEndArray(); + + json.WritePropertyName("ConsistentRead"); + json.WriteBooleanValue(statementRequest.ConsistentRead); + + if (statementRequest.ReturnValuesOnConditionCheckFailure != ReturnValuesOnConditionCheckFailure.None) + json.WriteReturnValuesOnConditionCheckFailure(statementRequest.ReturnValuesOnConditionCheckFailure); + + json.WriteEndObject(); + } + json.WriteEndArray(); + + if (_request.ReturnConsumedCapacity != ReturnConsumedCapacity.None) + json.WriteReturnConsumedCapacity(_request.ReturnConsumedCapacity); + + json.WriteEndObject(); + + return default; + } + } +} diff --git a/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementResponseParser.cs b/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementResponseParser.cs new file mode 100644 index 00000000..75913e24 --- /dev/null +++ b/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementResponseParser.cs @@ -0,0 +1,28 @@ +using EfficientDynamoDb.DocumentModel; +using EfficientDynamoDb.Internal.Operations.Shared; +using EfficientDynamoDb.Operations.BatchExecuteStatement; +using System; +using System.Collections.Generic; + +namespace EfficientDynamoDb.Internal.Operations.BatchExecuteStatement +{ + internal static class BatchExecuteStatementResponseParser + { + public static BatchExecuteStatementResponse Parse(Document response) + { + var responsesArray = response.TryGetValue("Responses", out var responsesAttribute) + ? (IReadOnlyList)responsesAttribute.AsListAttribute().Items + : Array.Empty(); + + var items = new Document[responsesArray.Count]; + for (var i = 0; i < responsesArray.Count; i++) + items[i] = responsesArray[i].AsDocument()["Item"].AsDocument(); + + return new BatchExecuteStatementResponse + { + Responses = items, + ConsumedCapacity = CapacityParser.ParseFullConsumedCapacities(response) + }; + } + } +} diff --git a/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementRequest.cs b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementRequest.cs new file mode 100644 index 00000000..00e67a5c --- /dev/null +++ b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementRequest.cs @@ -0,0 +1,24 @@ +using EfficientDynamoDb.Operations.Shared; +using System.Collections.Generic; + +namespace EfficientDynamoDb.Operations.BatchExecuteStatement +{ + /// + /// This operation allows you to perform batch reads or writes on data stored in DynamoDB, using PartiQL. Each read statement in a BatchExecuteStatement must specify an equality condition on all key attributes. This enforces that each SELECT statement in a batch returns at most a single item. + /// + public class BatchExecuteStatementRequest + { + /// + /// Gets and sets the property Statements. + /// + /// The list of PartiQL statements representing the batch to run. + /// + /// + public List Statements { get; set; } = new List(); + + /// + /// Determines the level of detail about provisioned throughput consumption that is returned in the response. + /// + public ReturnConsumedCapacity ReturnConsumedCapacity { get; set; } + } +} diff --git a/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementResponse.cs b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementResponse.cs new file mode 100644 index 00000000..bf134f72 --- /dev/null +++ b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementResponse.cs @@ -0,0 +1,64 @@ +using EfficientDynamoDb.Attributes; +using EfficientDynamoDb.Converters; +using EfficientDynamoDb.DocumentModel; +using EfficientDynamoDb.Internal.Converters.Json; +using EfficientDynamoDb.Operations.Shared.Capacity; +using System.Collections.Generic; + +namespace EfficientDynamoDb.Operations.BatchExecuteStatement +{ + public class BatchExecuteStatementResponse + { + /// + /// Gets and sets the property Responses. + /// + /// The response to each PartiQL statement in the batch. The values of the list are ordered + /// according to the ordering of the request statements. + /// + /// + public IReadOnlyList? Responses { get; set; } + + /// + /// Gets and sets the property ConsumedCapacity. + /// + /// The capacity units consumed by the entire operation. The values of the list are ordered + /// according to the ordering of the statements. + /// + /// + public List? ConsumedCapacity { get; set; } + } + + public class BatchExecuteStatementEntityResponse where TEntity : class + { + /// + /// The capacity units consumed by the entire operation. The values of the list are ordered according to the ordering of the statements. + /// + [DynamoDbProperty("ConsumedCapacity", typeof(JsonListDdbConverter<>))] + public List? ConsumedCapacity { get; set; } + + /// + /// The response to each PartiQL statement in the batch. The values of the list are ordered according to the ordering of the request statements. + /// + [DynamoDbProperty("Responses", typeof(BatchExecuteStatementItemsResponsesConverter<>))] + public IReadOnlyList> Responses { get; set; } = null!; + } + + public class BatchExecuteStatementItemResponse where TEntity : class + { + [DynamoDbProperty("Item")] + public TEntity? Item { get; set; } = null!; + } + + internal sealed class BatchExecuteStatementItemsResponsesConverter : JsonIReadOnlyListDdbConverter + { + public BatchExecuteStatementItemsResponsesConverter(DynamoDbContextMetadata metadata) : base(CreateValueConverter(metadata)) + { + } + + private static DdbConverter CreateValueConverter(DynamoDbContextMetadata metadata) + { + var transactResponseType = typeof(TValue); + return (DdbConverter)metadata.GetOrAddConverter(transactResponseType, typeof(JsonObjectDdbConverter<>).MakeGenericType(transactResponseType)); + } + } +} diff --git a/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementError.cs b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementError.cs new file mode 100644 index 00000000..3f6c7ef3 --- /dev/null +++ b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementError.cs @@ -0,0 +1,37 @@ +using EfficientDynamoDb.DocumentModel; +using System; +using System.Collections.Generic; +using System.Text; + +namespace EfficientDynamoDb.Operations.BatchExecuteStatement +{ + public class BatchStatementError + { + /// + /// Gets and sets the property Code. + /// + /// The error code associated with the failed PartiQL batch statement. + /// + /// + public BatchStatementErrorCodeEnum Code { get; set; } + + /// + /// Gets and sets the property Item. + /// + /// The item which caused the condition check to fail. This will be set if ReturnValuesOnConditionCheckFailure + /// is specified as ALL_OLD. + /// + /// + public Dictionary Item { get; set; } = new Dictionary(); + + /// + /// Gets and sets the property Message. + /// + /// The error message associated with the PartiQL batch response. + /// + /// + public string Message { get; set; } = string.Empty; + + + } +} diff --git a/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementErrorCodeEnum.cs b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementErrorCodeEnum.cs new file mode 100644 index 00000000..894729c0 --- /dev/null +++ b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementErrorCodeEnum.cs @@ -0,0 +1,17 @@ +namespace EfficientDynamoDb.Operations.BatchExecuteStatement +{ + public enum BatchStatementErrorCodeEnum + { + AccessDenied, + ConditionalCheckFailed, + DuplicateItem, + InternalServerError, + ItemCollectionSizeLimitExceeded, + ProvisionedThroughputExceeded, + RequestLimitExceeded, + ResourceNotFound, + ThrottlingError, + TransactionConflict, + ValidationError + } +} diff --git a/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementRequest.cs b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementRequest.cs new file mode 100644 index 00000000..41ead6b7 --- /dev/null +++ b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementRequest.cs @@ -0,0 +1,48 @@ +using EfficientDynamoDb.DocumentModel; +using EfficientDynamoDb.Operations.Shared; +using System.Collections.Generic; + +namespace EfficientDynamoDb.Operations.BatchExecuteStatement +{ + public class BatchStatementRequest + { + /// + /// Gets and sets the property Statement. + /// + /// A valid PartiQL statement. + /// + /// + public string Statement { get; set; } = string.Empty; + + /// + /// Gets and sets the property ConsistentRead. + /// + /// The read consistency of the PartiQL batch request. + /// + /// + public bool ConsistentRead { get; set; } + + /// + /// Gets and sets the property Parameters. + /// + /// The parameters associated with a PartiQL statement in the batch request. + /// + /// + public List Parameters { get; set; } = new List(); + + /// + /// Gets and sets the property ReturnValuesOnConditionCheckFailure. + /// + /// An optional parameter that returns the item attributes for a PartiQL batch request + /// operation that failed a condition check. + /// + /// + /// + /// There is no additional cost associated with requesting a return value aside from the + /// small network and processing overhead of receiving a larger response. No read capacity + /// units are consumed. + /// + /// + public ReturnValuesOnConditionCheckFailure ReturnValuesOnConditionCheckFailure { get; set; } + } +} From d9158e449795642ab9b41eb8d1779d42061f711c Mon Sep 17 00:00:00 2001 From: Chris Perez Date: Mon, 9 Sep 2024 12:05:40 -0600 Subject: [PATCH 03/18] add ExecuteTransaction in DynamoDbLowLevelContext --- .../DynamoDbLowLevelContext.cs | 8 +++ .../IDynamoDbLowLevelContext.cs | 2 + .../ExecuteTransactionRequestHttpContent.cs | 56 ++++++++++++++++ .../ExecuteTransactionResponseParser.cs | 28 ++++++++ .../ExecuteTransactionRequest.cs | 41 ++++++++++++ .../ExecuteTransactionResponse.cs | 64 +++++++++++++++++++ .../ParameterizedStatement.cs | 31 +++++++++ 7 files changed, 230 insertions(+) create mode 100644 src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionRequestHttpContent.cs create mode 100644 src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionResponseParser.cs create mode 100644 src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionRequest.cs create mode 100644 src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionResponse.cs create mode 100644 src/EfficientDynamoDb/Operations/ExecuteTransaction/ParameterizedStatement.cs diff --git a/src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelContext.cs b/src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelContext.cs index 63b8a227..1c92d150 100644 --- a/src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelContext.cs +++ b/src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelContext.cs @@ -168,6 +168,14 @@ public async Task BatchExecuteStatementAsync(Batc return BatchExecuteStatementResponseParser.Parse(result!); } + public async Task ExecuteTransactionAsync(ExecuteTransactionRequest request, CancellationToken cancellationToken = default) + { + var httpContent = new ExecuteTransactionRequestHttpContent(request); + using var response = await Api.SendAsync(Config, httpContent, cancellationToken).ConfigureAwait(false); + var result = await ReadDocumentAsync(response, QueryParsingOptions.Instance, cancellationToken).ConfigureAwait(false); + return ExecuteTransactionResponseParser.Parse(result!); + } + public T ToObject(Document document) where T : class => document.ToObject(Config.Metadata); public Document ToDocument(T entity) where T : class => entity.ToDocument(Config.Metadata); diff --git a/src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelContext.cs b/src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelContext.cs index 47ba8cf7..41d87dd2 100644 --- a/src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelContext.cs +++ b/src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelContext.cs @@ -43,6 +43,8 @@ public interface IDynamoDbLowLevelContext Task BatchExecuteStatementAsync(BatchExecuteStatementRequest request, CancellationToken cancellationToken = default); + Task ExecuteTransactionAsync(ExecuteTransactionRequest request, CancellationToken cancellationToken = default); + T ToObject(Document document) where T : class; Document ToDocument(T entity) where T : class; diff --git a/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionRequestHttpContent.cs b/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionRequestHttpContent.cs new file mode 100644 index 00000000..19dd442a --- /dev/null +++ b/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionRequestHttpContent.cs @@ -0,0 +1,56 @@ +using EfficientDynamoDb.Converters; +using EfficientDynamoDb.Internal.Extensions; +using EfficientDynamoDb.Internal.Operations.Shared; +using EfficientDynamoDb.Operations.ExecuteTransaction; +using EfficientDynamoDb.Operations.Shared; +using System.Threading.Tasks; + +namespace EfficientDynamoDb.Internal.Operations.ExecuteTransaction +{ + internal class ExecuteTransactionRequestHttpContent : DynamoDbHttpContent + { + private readonly ExecuteTransactionRequest _request; + + public ExecuteTransactionRequestHttpContent(ExecuteTransactionRequest request) : base("DynamoDB_20120810.ExecuteTransaction") + { + _request = request; + } + + protected override ValueTask WriteDataAsync(DdbWriter writer) + { + var json = writer.JsonWriter; + json.WriteStartObject(); + + json.WritePropertyName("TransactStatements"); + json.WriteStartArray(); + foreach (var statement in _request.TransactStatements) + { + json.WriteStartObject(); + + json.WritePropertyName("Statement"); + json.WriteStringValue(statement.Statement); + + json.WritePropertyName("Parameters"); + json.WriteStartArray(); + foreach (var parameter in statement.Parameters) + { + parameter.Write(json); + } + json.WriteEndArray(); + + json.WriteEndObject(); + } + json.WriteEndArray(); + + json.WritePropertyName("ClientRequestToken"); + json.WriteStringValue(_request.ClientRequestToken); + + if (_request.ReturnConsumedCapacity != ReturnConsumedCapacity.None) + json.WriteReturnConsumedCapacity(_request.ReturnConsumedCapacity); + + json.WriteEndObject(); + + return default; + } + } +} diff --git a/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionResponseParser.cs b/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionResponseParser.cs new file mode 100644 index 00000000..9ce9e5be --- /dev/null +++ b/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionResponseParser.cs @@ -0,0 +1,28 @@ +using EfficientDynamoDb.DocumentModel; +using EfficientDynamoDb.Internal.Operations.Shared; +using EfficientDynamoDb.Operations.ExecuteTransaction; +using System; +using System.Collections.Generic; + +namespace EfficientDynamoDb.Internal.Operations.ExecuteTransaction +{ + internal static class ExecuteTransactionResponseParser + { + public static ExecuteTransactionResponse Parse(Document response) + { + var responsesArray = response.TryGetValue("Responses", out var responsesAttribute) + ? (IReadOnlyList)responsesAttribute.AsListAttribute().Items + : Array.Empty(); + + var items = new Document[responsesArray.Count]; + for (var i = 0; i < responsesArray.Count; i++) + items[i] = responsesArray[i].AsDocument()["Item"].AsDocument(); + + return new ExecuteTransactionResponse + { + Responses = items, + ConsumedCapacity = CapacityParser.ParseFullConsumedCapacities(response) + }; + } + } +} diff --git a/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionRequest.cs b/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionRequest.cs new file mode 100644 index 00000000..9179db70 --- /dev/null +++ b/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionRequest.cs @@ -0,0 +1,41 @@ +using EfficientDynamoDb.Operations.Shared; +using System; +using System.Collections.Generic; + +namespace EfficientDynamoDb.Operations.ExecuteTransaction +{ + /// + /// This operation allows you to perform batch reads or writes on data stored in DynamoDB, using PartiQL. + /// Each read statement in a BatchExecuteStatement must specify an equality condition on all key attributes. + /// This enforces that each SELECT statement in a batch returns at most a single item. + /// + public class ExecuteTransactionRequest + { + /// + /// Gets and sets the property TransactStatements. + /// + /// The list of PartiQL statements representing the transaction to run. + /// + /// + public List TransactStatements { get; set; } = new List(); + + /// + /// Gets and sets the property ClientRequestToken. + /// + /// Set this value to get remaining results, if NextToken was returned in the statement + /// response. + /// + /// + public string ClientRequestToken { get; set; } = Guid.NewGuid().ToString(); + + /// + /// Gets and sets the property ReturnConsumedCapacity. + /// + /// Determines the level of detail about either provisioned or on-demand throughput consumption + /// that is returned in the response. For more information, see TransactGetItems + /// and TransactWriteItems. + /// + /// + public ReturnConsumedCapacity ReturnConsumedCapacity { get; set; } + } +} diff --git a/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionResponse.cs b/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionResponse.cs new file mode 100644 index 00000000..8a6474bd --- /dev/null +++ b/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionResponse.cs @@ -0,0 +1,64 @@ +using EfficientDynamoDb.Attributes; +using EfficientDynamoDb.Converters; +using EfficientDynamoDb.DocumentModel; +using EfficientDynamoDb.Internal.Converters.Json; +using EfficientDynamoDb.Operations.Shared.Capacity; +using System.Collections.Generic; + +namespace EfficientDynamoDb.Operations.ExecuteTransaction +{ + public class ExecuteTransactionResponse + { + /// + /// Gets and sets the property Responses. + /// + /// The response to each PartiQL statement in the batch. The values of the list are ordered + /// according to the ordering of the request statements. + /// + /// + public IReadOnlyList? Responses { get; set; } + + /// + /// Gets and sets the property ConsumedCapacity. + /// + /// The capacity units consumed by the entire operation. The values of the list are ordered + /// according to the ordering of the statements. + /// + /// + public List? ConsumedCapacity { get; set; } + } + + public class ExecuteTransactionEntityResponse where TEntity : class + { + /// + /// The capacity units consumed by the entire operation. The values of the list are ordered according to the ordering of the statements. + /// + [DynamoDbProperty("ConsumedCapacity", typeof(JsonListDdbConverter<>))] + public List? ConsumedCapacity { get; set; } + + /// + /// The response to each PartiQL statement in the batch. The values of the list are ordered according to the ordering of the request statements. + /// + [DynamoDbProperty("Responses", typeof(ExecuteTransactionItemsResponsesConverter<>))] + public IReadOnlyList> Responses { get; set; } = null!; + } + + public class ExecuteTransactionItemResponse where TEntity : class + { + [DynamoDbProperty("Item")] + public TEntity? Item { get; set; } = null!; + } + + internal sealed class ExecuteTransactionItemsResponsesConverter : JsonIReadOnlyListDdbConverter + { + public ExecuteTransactionItemsResponsesConverter(DynamoDbContextMetadata metadata) : base(CreateValueConverter(metadata)) + { + } + + private static DdbConverter CreateValueConverter(DynamoDbContextMetadata metadata) + { + var transactResponseType = typeof(TValue); + return (DdbConverter)metadata.GetOrAddConverter(transactResponseType, typeof(JsonObjectDdbConverter<>).MakeGenericType(transactResponseType)); + } + } +} diff --git a/src/EfficientDynamoDb/Operations/ExecuteTransaction/ParameterizedStatement.cs b/src/EfficientDynamoDb/Operations/ExecuteTransaction/ParameterizedStatement.cs new file mode 100644 index 00000000..693b288b --- /dev/null +++ b/src/EfficientDynamoDb/Operations/ExecuteTransaction/ParameterizedStatement.cs @@ -0,0 +1,31 @@ +using EfficientDynamoDb.DocumentModel; +using EfficientDynamoDb.Operations.Shared; +using System.Collections.Generic; + +namespace EfficientDynamoDb.Operations.ExecuteTransaction +{ + public class ParameterizedStatement + { + /// + /// Gets and sets the property Statement. + /// + /// A PartiQL statement that uses parameters. + /// + /// + public string Statement { get; set; } = string.Empty; + + /// + /// Gets and sets the property Parameters. + /// + /// The parameter values. + /// + /// + //[AWSProperty(Min = 1)] // TODO check if this is needed + public List Parameters { get; set; } = new List(); + + /// + /// Use to get the item attributes if the Delete condition fails. For , the valid values are: NONE and ALL_OLD. + /// + public ReturnValuesOnConditionCheckFailure ReturnValuesOnConditionCheckFailure { get; set; } + } +} From 4fa4526c060038c6706e4c06fcfdb7a7fe926bca Mon Sep 17 00:00:00 2001 From: Chris Perez Date: Mon, 9 Sep 2024 12:06:19 -0600 Subject: [PATCH 04/18] add ExecuteStatement in DynamoDbContext --- .../DynamoDbContext.ExecuteStatement.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/EfficientDynamoDb/DynamoDbContext/DynamoDbContext.ExecuteStatement.cs diff --git a/src/EfficientDynamoDb/DynamoDbContext/DynamoDbContext.ExecuteStatement.cs b/src/EfficientDynamoDb/DynamoDbContext/DynamoDbContext.ExecuteStatement.cs new file mode 100644 index 00000000..75221b5c --- /dev/null +++ b/src/EfficientDynamoDb/DynamoDbContext/DynamoDbContext.ExecuteStatement.cs @@ -0,0 +1,23 @@ +using EfficientDynamoDb.Internal.Operations.ExecuteStatement; +using EfficientDynamoDb.Operations.ExecuteStatement; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace EfficientDynamoDb +{ + public partial class DynamoDbContext + { + public async Task> ExecuteStatementAsync(ExecuteStatementRequest request, CancellationToken cancellationToken = default) where TEntity : class + { + var httpContent = new ExecuteStatementRequestHttpContent(request); + using var response = await Api.SendAsync(Config, httpContent, cancellationToken).ConfigureAwait(false); + var result = await ReadAsync>(response, cancellationToken).ConfigureAwait(false); + var entities = new List(result.Items.Count); + foreach (var item in result.Items) + entities.Add(item); + + return entities; + } + } +} From 9495be29598221a1531b3401d790182a247bdc9c Mon Sep 17 00:00:00 2001 From: Chris Perez Date: Mon, 9 Sep 2024 12:06:31 -0600 Subject: [PATCH 05/18] add BatchExecuteStatement in DynamoDbContext --- .../DynamoDbContext.BatchExecuteStatement.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/EfficientDynamoDb/DynamoDbContext/DynamoDbContext.BatchExecuteStatement.cs diff --git a/src/EfficientDynamoDb/DynamoDbContext/DynamoDbContext.BatchExecuteStatement.cs b/src/EfficientDynamoDb/DynamoDbContext/DynamoDbContext.BatchExecuteStatement.cs new file mode 100644 index 00000000..7e2cd2e1 --- /dev/null +++ b/src/EfficientDynamoDb/DynamoDbContext/DynamoDbContext.BatchExecuteStatement.cs @@ -0,0 +1,23 @@ +using EfficientDynamoDb.Internal.Operations.BatchExecuteStatement; +using EfficientDynamoDb.Operations.BatchExecuteStatement; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace EfficientDynamoDb +{ + public partial class DynamoDbContext + { + public async Task> BatchExecuteStatementAsync(BatchExecuteStatementRequest request, CancellationToken cancellationToken = default) where TEntity : class + { + var httpContent = new BatchExecuteStatementRequestHttpContent(request); + using var response = await Api.SendAsync(Config, httpContent, cancellationToken).ConfigureAwait(false); + var result = await ReadAsync>(response, cancellationToken).ConfigureAwait(false); + var entities = new List(result.Responses.Count); + foreach (var item in result.Responses) + entities.Add(item.Item); + + return entities; + } + } +} From 5dbc0c2cbf56328b1e68ca1d4bc0ef7f9c5a057d Mon Sep 17 00:00:00 2001 From: Chris Perez Date: Mon, 9 Sep 2024 12:06:46 -0600 Subject: [PATCH 06/18] add ExecuteTransaction in DynamoDbContext --- .../DynamoDbContext.ExecuteTransaction.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/EfficientDynamoDb/DynamoDbContext/DynamoDbContext.ExecuteTransaction.cs diff --git a/src/EfficientDynamoDb/DynamoDbContext/DynamoDbContext.ExecuteTransaction.cs b/src/EfficientDynamoDb/DynamoDbContext/DynamoDbContext.ExecuteTransaction.cs new file mode 100644 index 00000000..0a9e5683 --- /dev/null +++ b/src/EfficientDynamoDb/DynamoDbContext/DynamoDbContext.ExecuteTransaction.cs @@ -0,0 +1,23 @@ +using EfficientDynamoDb.Internal.Operations.ExecuteTransaction; +using EfficientDynamoDb.Operations.ExecuteTransaction; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace EfficientDynamoDb +{ + public partial class DynamoDbContext + { + public async Task> ExecuteTransactionAsync(ExecuteTransactionRequest request, CancellationToken cancellationToken = default) where TEntity : class + { + var httpContent = new ExecuteTransactionRequestHttpContent(request); + using var response = await Api.SendAsync(Config, httpContent, cancellationToken).ConfigureAwait(false); + var result = await ReadAsync>(response, cancellationToken).ConfigureAwait(false); + var entities = new List(result.Responses.Count); + foreach (var item in result.Responses) + entities.Add(item.Item); + + return entities; + } + } +} From 80508bce010e5a7b75e5339465f83df63ee81d15 Mon Sep 17 00:00:00 2001 From: Chris Perez Date: Wed, 18 Sep 2024 22:40:50 -0600 Subject: [PATCH 07/18] remove BatchStatementError --- .../BatchStatementError.cs | 37 ------------------- .../BatchStatementErrorCodeEnum.cs | 17 --------- 2 files changed, 54 deletions(-) delete mode 100644 src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementError.cs delete mode 100644 src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementErrorCodeEnum.cs diff --git a/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementError.cs b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementError.cs deleted file mode 100644 index 3f6c7ef3..00000000 --- a/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementError.cs +++ /dev/null @@ -1,37 +0,0 @@ -using EfficientDynamoDb.DocumentModel; -using System; -using System.Collections.Generic; -using System.Text; - -namespace EfficientDynamoDb.Operations.BatchExecuteStatement -{ - public class BatchStatementError - { - /// - /// Gets and sets the property Code. - /// - /// The error code associated with the failed PartiQL batch statement. - /// - /// - public BatchStatementErrorCodeEnum Code { get; set; } - - /// - /// Gets and sets the property Item. - /// - /// The item which caused the condition check to fail. This will be set if ReturnValuesOnConditionCheckFailure - /// is specified as ALL_OLD. - /// - /// - public Dictionary Item { get; set; } = new Dictionary(); - - /// - /// Gets and sets the property Message. - /// - /// The error message associated with the PartiQL batch response. - /// - /// - public string Message { get; set; } = string.Empty; - - - } -} diff --git a/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementErrorCodeEnum.cs b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementErrorCodeEnum.cs deleted file mode 100644 index 894729c0..00000000 --- a/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementErrorCodeEnum.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace EfficientDynamoDb.Operations.BatchExecuteStatement -{ - public enum BatchStatementErrorCodeEnum - { - AccessDenied, - ConditionalCheckFailed, - DuplicateItem, - InternalServerError, - ItemCollectionSizeLimitExceeded, - ProvisionedThroughputExceeded, - RequestLimitExceeded, - ResourceNotFound, - ThrottlingError, - TransactionConflict, - ValidationError - } -} From 4baf9a4b8b50505e04203b2e30baf73fe624f9d6 Mon Sep 17 00:00:00 2001 From: Chris Perez Date: Wed, 18 Sep 2024 22:49:38 -0600 Subject: [PATCH 08/18] remove PartiQL API from high-level API --- .../DynamoDbContext.BatchExecuteStatement.cs | 23 ------------- .../DynamoDbContext.ExecuteStatement.cs | 23 ------------- .../DynamoDbContext.ExecuteTransaction.cs | 23 ------------- .../BatchExecuteStatementResponse.cs | 34 ------------------- .../ExecuteStatementResponse.cs | 34 ------------------- .../ExecuteTransactionResponse.cs | 34 ------------------- 6 files changed, 171 deletions(-) delete mode 100644 src/EfficientDynamoDb/DynamoDbContext/DynamoDbContext.BatchExecuteStatement.cs delete mode 100644 src/EfficientDynamoDb/DynamoDbContext/DynamoDbContext.ExecuteStatement.cs delete mode 100644 src/EfficientDynamoDb/DynamoDbContext/DynamoDbContext.ExecuteTransaction.cs diff --git a/src/EfficientDynamoDb/DynamoDbContext/DynamoDbContext.BatchExecuteStatement.cs b/src/EfficientDynamoDb/DynamoDbContext/DynamoDbContext.BatchExecuteStatement.cs deleted file mode 100644 index 7e2cd2e1..00000000 --- a/src/EfficientDynamoDb/DynamoDbContext/DynamoDbContext.BatchExecuteStatement.cs +++ /dev/null @@ -1,23 +0,0 @@ -using EfficientDynamoDb.Internal.Operations.BatchExecuteStatement; -using EfficientDynamoDb.Operations.BatchExecuteStatement; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace EfficientDynamoDb -{ - public partial class DynamoDbContext - { - public async Task> BatchExecuteStatementAsync(BatchExecuteStatementRequest request, CancellationToken cancellationToken = default) where TEntity : class - { - var httpContent = new BatchExecuteStatementRequestHttpContent(request); - using var response = await Api.SendAsync(Config, httpContent, cancellationToken).ConfigureAwait(false); - var result = await ReadAsync>(response, cancellationToken).ConfigureAwait(false); - var entities = new List(result.Responses.Count); - foreach (var item in result.Responses) - entities.Add(item.Item); - - return entities; - } - } -} diff --git a/src/EfficientDynamoDb/DynamoDbContext/DynamoDbContext.ExecuteStatement.cs b/src/EfficientDynamoDb/DynamoDbContext/DynamoDbContext.ExecuteStatement.cs deleted file mode 100644 index 75221b5c..00000000 --- a/src/EfficientDynamoDb/DynamoDbContext/DynamoDbContext.ExecuteStatement.cs +++ /dev/null @@ -1,23 +0,0 @@ -using EfficientDynamoDb.Internal.Operations.ExecuteStatement; -using EfficientDynamoDb.Operations.ExecuteStatement; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace EfficientDynamoDb -{ - public partial class DynamoDbContext - { - public async Task> ExecuteStatementAsync(ExecuteStatementRequest request, CancellationToken cancellationToken = default) where TEntity : class - { - var httpContent = new ExecuteStatementRequestHttpContent(request); - using var response = await Api.SendAsync(Config, httpContent, cancellationToken).ConfigureAwait(false); - var result = await ReadAsync>(response, cancellationToken).ConfigureAwait(false); - var entities = new List(result.Items.Count); - foreach (var item in result.Items) - entities.Add(item); - - return entities; - } - } -} diff --git a/src/EfficientDynamoDb/DynamoDbContext/DynamoDbContext.ExecuteTransaction.cs b/src/EfficientDynamoDb/DynamoDbContext/DynamoDbContext.ExecuteTransaction.cs deleted file mode 100644 index 0a9e5683..00000000 --- a/src/EfficientDynamoDb/DynamoDbContext/DynamoDbContext.ExecuteTransaction.cs +++ /dev/null @@ -1,23 +0,0 @@ -using EfficientDynamoDb.Internal.Operations.ExecuteTransaction; -using EfficientDynamoDb.Operations.ExecuteTransaction; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace EfficientDynamoDb -{ - public partial class DynamoDbContext - { - public async Task> ExecuteTransactionAsync(ExecuteTransactionRequest request, CancellationToken cancellationToken = default) where TEntity : class - { - var httpContent = new ExecuteTransactionRequestHttpContent(request); - using var response = await Api.SendAsync(Config, httpContent, cancellationToken).ConfigureAwait(false); - var result = await ReadAsync>(response, cancellationToken).ConfigureAwait(false); - var entities = new List(result.Responses.Count); - foreach (var item in result.Responses) - entities.Add(item.Item); - - return entities; - } - } -} diff --git a/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementResponse.cs b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementResponse.cs index bf134f72..fd05e3b4 100644 --- a/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementResponse.cs +++ b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementResponse.cs @@ -27,38 +27,4 @@ public class BatchExecuteStatementResponse /// public List? ConsumedCapacity { get; set; } } - - public class BatchExecuteStatementEntityResponse where TEntity : class - { - /// - /// The capacity units consumed by the entire operation. The values of the list are ordered according to the ordering of the statements. - /// - [DynamoDbProperty("ConsumedCapacity", typeof(JsonListDdbConverter<>))] - public List? ConsumedCapacity { get; set; } - - /// - /// The response to each PartiQL statement in the batch. The values of the list are ordered according to the ordering of the request statements. - /// - [DynamoDbProperty("Responses", typeof(BatchExecuteStatementItemsResponsesConverter<>))] - public IReadOnlyList> Responses { get; set; } = null!; - } - - public class BatchExecuteStatementItemResponse where TEntity : class - { - [DynamoDbProperty("Item")] - public TEntity? Item { get; set; } = null!; - } - - internal sealed class BatchExecuteStatementItemsResponsesConverter : JsonIReadOnlyListDdbConverter - { - public BatchExecuteStatementItemsResponsesConverter(DynamoDbContextMetadata metadata) : base(CreateValueConverter(metadata)) - { - } - - private static DdbConverter CreateValueConverter(DynamoDbContextMetadata metadata) - { - var transactResponseType = typeof(TValue); - return (DdbConverter)metadata.GetOrAddConverter(transactResponseType, typeof(JsonObjectDdbConverter<>).MakeGenericType(transactResponseType)); - } - } } diff --git a/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementResponse.cs b/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementResponse.cs index 7e9dc850..5d9a9571 100644 --- a/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementResponse.cs +++ b/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementResponse.cs @@ -49,38 +49,4 @@ public class ExecuteStatementResponse /// public FullConsumedCapacity? ConsumedCapacity { get; set; } } - - public class ExecuteStatementEntityResponse - { - /// - /// An array of item attributes that match the query criteria. Each element in this array consists of an attribute name and the value for that attribute. - /// - [DynamoDbProperty("Items", typeof(JsonIReadOnlyListHintDdbConverter<>))] - public IReadOnlyList Items { get; set; } = null!; - - /// - /// The primary key of the item where the operation stopped, inclusive of the previous result set. Use this value to start a new operation, excluding this value in the new request.

- /// If is null, then the "last page" of results has been processed and there is no more data to be retrieved.

- /// If is not null, it does not necessarily mean that there is more data in the result set. The only way to know when you have reached the end of the result set is when is null. - ///
- [DynamoDbProperty("LastEvaluatedKey", typeof(PaginationDdbConverter))] - public string? LastEvaluatedKey { get; set; } - - /// - /// Gets and sets the property NextToken. - /// - /// If the response of a read request exceeds the response payload limit DynamoDB will - /// set this value in the response. If set, you can use that this value in the subsequent - /// request to get the remaining results. - /// - /// - [DynamoDbProperty("NextToken")] - public string NextToken { get; set; } = string.Empty; - - /// - /// The capacity units consumed by the Query operation. The data returned includes the total provisioned throughput consumed, along with statistics for the table and any indexes involved in the operation. is only returned if the parameter was specified. - /// - [DynamoDbProperty("ConsumedCapacity", typeof(JsonObjectDdbConverter))] - public FullConsumedCapacity? ConsumedCapacity { get; set; } - } } diff --git a/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionResponse.cs b/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionResponse.cs index 8a6474bd..eed7764c 100644 --- a/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionResponse.cs +++ b/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionResponse.cs @@ -27,38 +27,4 @@ public class ExecuteTransactionResponse /// public List? ConsumedCapacity { get; set; } } - - public class ExecuteTransactionEntityResponse where TEntity : class - { - /// - /// The capacity units consumed by the entire operation. The values of the list are ordered according to the ordering of the statements. - /// - [DynamoDbProperty("ConsumedCapacity", typeof(JsonListDdbConverter<>))] - public List? ConsumedCapacity { get; set; } - - /// - /// The response to each PartiQL statement in the batch. The values of the list are ordered according to the ordering of the request statements. - /// - [DynamoDbProperty("Responses", typeof(ExecuteTransactionItemsResponsesConverter<>))] - public IReadOnlyList> Responses { get; set; } = null!; - } - - public class ExecuteTransactionItemResponse where TEntity : class - { - [DynamoDbProperty("Item")] - public TEntity? Item { get; set; } = null!; - } - - internal sealed class ExecuteTransactionItemsResponsesConverter : JsonIReadOnlyListDdbConverter - { - public ExecuteTransactionItemsResponsesConverter(DynamoDbContextMetadata metadata) : base(CreateValueConverter(metadata)) - { - } - - private static DdbConverter CreateValueConverter(DynamoDbContextMetadata metadata) - { - var transactResponseType = typeof(TValue); - return (DdbConverter)metadata.GetOrAddConverter(transactResponseType, typeof(JsonObjectDdbConverter<>).MakeGenericType(transactResponseType)); - } - } } From 140ddaaedd83ec1f95b5215a5944475e7cea8f85 Mon Sep 17 00:00:00 2001 From: Chris Perez Date: Wed, 18 Sep 2024 23:00:05 -0600 Subject: [PATCH 09/18] replace List with IReadOnlyList --- .../BatchExecuteStatement/BatchExecuteStatementRequest.cs | 3 ++- .../BatchExecuteStatement/BatchExecuteStatementResponse.cs | 7 ++----- .../BatchExecuteStatement/BatchStatementRequest.cs | 3 ++- .../Operations/ExecuteStatement/ExecuteStatementRequest.cs | 3 ++- .../ExecuteStatement/ExecuteStatementResponse.cs | 6 +----- .../ExecuteTransaction/ExecuteTransactionRequest.cs | 2 +- .../ExecuteTransaction/ExecuteTransactionResponse.cs | 7 ++----- .../ExecuteTransaction/ParameterizedStatement.cs | 4 ++-- 8 files changed, 14 insertions(+), 21 deletions(-) diff --git a/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementRequest.cs b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementRequest.cs index 00e67a5c..4f9761f0 100644 --- a/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementRequest.cs +++ b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementRequest.cs @@ -1,4 +1,5 @@ using EfficientDynamoDb.Operations.Shared; +using System; using System.Collections.Generic; namespace EfficientDynamoDb.Operations.BatchExecuteStatement @@ -14,7 +15,7 @@ public class BatchExecuteStatementRequest /// The list of PartiQL statements representing the batch to run. /// /// - public List Statements { get; set; } = new List(); + public IReadOnlyList Statements { get; set; } = Array.Empty(); /// /// Determines the level of detail about provisioned throughput consumption that is returned in the response. diff --git a/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementResponse.cs b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementResponse.cs index fd05e3b4..6e16e8dc 100644 --- a/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementResponse.cs +++ b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementResponse.cs @@ -1,7 +1,4 @@ -using EfficientDynamoDb.Attributes; -using EfficientDynamoDb.Converters; -using EfficientDynamoDb.DocumentModel; -using EfficientDynamoDb.Internal.Converters.Json; +using EfficientDynamoDb.DocumentModel; using EfficientDynamoDb.Operations.Shared.Capacity; using System.Collections.Generic; @@ -25,6 +22,6 @@ public class BatchExecuteStatementResponse /// according to the ordering of the statements. /// /// - public List? ConsumedCapacity { get; set; } + public IReadOnlyList? ConsumedCapacity { get; set; } } } diff --git a/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementRequest.cs b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementRequest.cs index 41ead6b7..7aabc220 100644 --- a/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementRequest.cs +++ b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementRequest.cs @@ -1,5 +1,6 @@ using EfficientDynamoDb.DocumentModel; using EfficientDynamoDb.Operations.Shared; +using System; using System.Collections.Generic; namespace EfficientDynamoDb.Operations.BatchExecuteStatement @@ -28,7 +29,7 @@ public class BatchStatementRequest /// The parameters associated with a PartiQL statement in the batch request. /// /// - public List Parameters { get; set; } = new List(); + public IReadOnlyList Parameters { get; set; } = Array.Empty(); /// /// Gets and sets the property ReturnValuesOnConditionCheckFailure. diff --git a/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementRequest.cs b/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementRequest.cs index 95e2bc59..a6e043b4 100644 --- a/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementRequest.cs +++ b/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementRequest.cs @@ -1,5 +1,6 @@ using EfficientDynamoDb.DocumentModel; using EfficientDynamoDb.Operations.Shared; +using System; using System.Collections.Generic; namespace EfficientDynamoDb.Operations.ExecuteStatement @@ -20,7 +21,7 @@ public class ExecuteStatementRequest /// The parameters for the PartiQL statement, if any. /// /// - public List Parameters { get; set; } = new List(); + public IReadOnlyList Parameters { get; set; } = Array.Empty(); /// /// Gets and sets the property ConsistentRead. diff --git a/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementResponse.cs b/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementResponse.cs index 5d9a9571..d642c1d5 100644 --- a/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementResponse.cs +++ b/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementResponse.cs @@ -1,9 +1,5 @@ -using EfficientDynamoDb.Attributes; -using EfficientDynamoDb.DocumentModel; -using EfficientDynamoDb.Internal.Converters; -using EfficientDynamoDb.Internal.Converters.Json; +using EfficientDynamoDb.DocumentModel; using EfficientDynamoDb.Operations.Shared.Capacity; -using EfficientDynamoDb.Operations.TransactGetItems; using System.Collections.Generic; namespace EfficientDynamoDb.Operations.ExecuteStatement diff --git a/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionRequest.cs b/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionRequest.cs index 9179db70..da31f412 100644 --- a/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionRequest.cs +++ b/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionRequest.cs @@ -17,7 +17,7 @@ public class ExecuteTransactionRequest /// The list of PartiQL statements representing the transaction to run. /// /// - public List TransactStatements { get; set; } = new List(); + public IReadOnlyList TransactStatements { get; set; } = Array.Empty(); /// /// Gets and sets the property ClientRequestToken. diff --git a/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionResponse.cs b/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionResponse.cs index eed7764c..a1141cb2 100644 --- a/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionResponse.cs +++ b/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionResponse.cs @@ -1,7 +1,4 @@ -using EfficientDynamoDb.Attributes; -using EfficientDynamoDb.Converters; -using EfficientDynamoDb.DocumentModel; -using EfficientDynamoDb.Internal.Converters.Json; +using EfficientDynamoDb.DocumentModel; using EfficientDynamoDb.Operations.Shared.Capacity; using System.Collections.Generic; @@ -25,6 +22,6 @@ public class ExecuteTransactionResponse /// according to the ordering of the statements. /// /// - public List? ConsumedCapacity { get; set; } + public IReadOnlyList? ConsumedCapacity { get; set; } } } diff --git a/src/EfficientDynamoDb/Operations/ExecuteTransaction/ParameterizedStatement.cs b/src/EfficientDynamoDb/Operations/ExecuteTransaction/ParameterizedStatement.cs index 693b288b..f9ff3142 100644 --- a/src/EfficientDynamoDb/Operations/ExecuteTransaction/ParameterizedStatement.cs +++ b/src/EfficientDynamoDb/Operations/ExecuteTransaction/ParameterizedStatement.cs @@ -1,5 +1,6 @@ using EfficientDynamoDb.DocumentModel; using EfficientDynamoDb.Operations.Shared; +using System; using System.Collections.Generic; namespace EfficientDynamoDb.Operations.ExecuteTransaction @@ -20,8 +21,7 @@ public class ParameterizedStatement /// The parameter values. /// /// - //[AWSProperty(Min = 1)] // TODO check if this is needed - public List Parameters { get; set; } = new List(); + public IReadOnlyList Parameters { get; set; } = Array.Empty(); /// /// Use to get the item attributes if the Delete condition fails. For , the valid values are: NONE and ALL_OLD. From 2b99750d0d713dda8a7672e708db7aaf76bb898d Mon Sep 17 00:00:00 2001 From: Chris Perez Date: Wed, 18 Sep 2024 23:57:22 -0600 Subject: [PATCH 10/18] convert properties to nullable --- .../Operations/ExecuteStatement/ExecuteStatementRequest.cs | 4 ++-- .../Operations/ExecuteStatement/ExecuteStatementResponse.cs | 2 +- .../ExecuteTransaction/ExecuteTransactionRequest.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementRequest.cs b/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementRequest.cs index a6e043b4..c9f20782 100644 --- a/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementRequest.cs +++ b/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementRequest.cs @@ -45,7 +45,7 @@ public class ExecuteStatementRequest /// continue the operation. /// /// - public int Limit { get; set; } + public int? Limit { get; set; } /// /// Gets and sets the property NextToken. @@ -54,7 +54,7 @@ public class ExecuteStatementRequest /// response. /// /// - public string NextToken { get; set; } = string.Empty; + public string? NextToken { get; set; } /// /// Determines the level of detail about provisioned throughput consumption that is returned in the response. diff --git a/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementResponse.cs b/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementResponse.cs index d642c1d5..b684003f 100644 --- a/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementResponse.cs +++ b/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementResponse.cs @@ -38,7 +38,7 @@ public class ExecuteStatementResponse /// request to get the remaining results. /// /// - public string NextToken { get; set; } = string.Empty; + public string? NextToken { get; set; } /// /// The capacity units consumed by the entire ExecuteStatement operation. The values of the list are ordered according to the ordering of the request parameter. diff --git a/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionRequest.cs b/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionRequest.cs index da31f412..d2906d70 100644 --- a/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionRequest.cs +++ b/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionRequest.cs @@ -26,7 +26,7 @@ public class ExecuteTransactionRequest /// response. /// /// - public string ClientRequestToken { get; set; } = Guid.NewGuid().ToString(); + public string? ClientRequestToken { get; set; } /// /// Gets and sets the property ReturnConsumedCapacity. From d94dca7d4b1c06833e789257c81ad9f23e1c8e80 Mon Sep 17 00:00:00 2001 From: Chris Perez Date: Thu, 19 Sep 2024 00:09:48 -0600 Subject: [PATCH 11/18] changes in RequestHttpContent --- .../BatchExecuteStatementRequestHttpContent.cs | 9 +++------ .../ExecuteStatementRequestHttpContent.cs | 14 +++++++------- .../ExecuteTransactionRequestHttpContent.cs | 7 +++---- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementRequestHttpContent.cs b/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementRequestHttpContent.cs index f97053b4..a0519391 100644 --- a/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementRequestHttpContent.cs +++ b/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementRequestHttpContent.cs @@ -3,8 +3,6 @@ using EfficientDynamoDb.Internal.Operations.Shared; using EfficientDynamoDb.Operations.BatchExecuteStatement; using EfficientDynamoDb.Operations.Shared; -using System.Text; -using System; using System.Threading.Tasks; namespace EfficientDynamoDb.Internal.Operations.BatchExecuteStatement @@ -29,8 +27,7 @@ protected override ValueTask WriteDataAsync(DdbWriter writer) { json.WriteStartObject(); - json.WritePropertyName("Statement"); - json.WriteStringValue(statementRequest.Statement); + json.WriteString("Statement", statementRequest.Statement); json.WritePropertyName("Parameters"); json.WriteStartArray(); @@ -40,8 +37,8 @@ protected override ValueTask WriteDataAsync(DdbWriter writer) } json.WriteEndArray(); - json.WritePropertyName("ConsistentRead"); - json.WriteBooleanValue(statementRequest.ConsistentRead); + if (statementRequest.ConsistentRead) + json.WriteBoolean("ConsistentRead", true); if (statementRequest.ReturnValuesOnConditionCheckFailure != ReturnValuesOnConditionCheckFailure.None) json.WriteReturnValuesOnConditionCheckFailure(statementRequest.ReturnValuesOnConditionCheckFailure); diff --git a/src/EfficientDynamoDb/Internal/Operations/ExecuteStatement/ExecuteStatementRequestHttpContent.cs b/src/EfficientDynamoDb/Internal/Operations/ExecuteStatement/ExecuteStatementRequestHttpContent.cs index 264997d7..5bb97fc0 100644 --- a/src/EfficientDynamoDb/Internal/Operations/ExecuteStatement/ExecuteStatementRequestHttpContent.cs +++ b/src/EfficientDynamoDb/Internal/Operations/ExecuteStatement/ExecuteStatementRequestHttpContent.cs @@ -32,14 +32,14 @@ protected override ValueTask WriteDataAsync(DdbWriter writer) } json.WriteEndArray(); - json.WritePropertyName("ConsistentRead"); - json.WriteBooleanValue(_request.ConsistentRead); + if (_request.ConsistentRead) + json.WriteBoolean("ConsistentRead", true); - if (_request.Limit > 0) - { - json.WritePropertyName("Limit"); - json.WriteNumberValue(_request.Limit); - } + if (_request.Limit.HasValue) + json.WriteNumber("Limit", _request.Limit.Value); + + if (_request.NextToken != null) + json.WriteString("NextToken", _request.NextToken); if (_request.ReturnConsumedCapacity != ReturnConsumedCapacity.None) json.WriteReturnConsumedCapacity(_request.ReturnConsumedCapacity); diff --git a/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionRequestHttpContent.cs b/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionRequestHttpContent.cs index 19dd442a..d93fa1d1 100644 --- a/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionRequestHttpContent.cs +++ b/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionRequestHttpContent.cs @@ -27,8 +27,7 @@ protected override ValueTask WriteDataAsync(DdbWriter writer) { json.WriteStartObject(); - json.WritePropertyName("Statement"); - json.WriteStringValue(statement.Statement); + json.WriteString("Statement", statement.Statement); json.WritePropertyName("Parameters"); json.WriteStartArray(); @@ -42,8 +41,8 @@ protected override ValueTask WriteDataAsync(DdbWriter writer) } json.WriteEndArray(); - json.WritePropertyName("ClientRequestToken"); - json.WriteStringValue(_request.ClientRequestToken); + if (_request.ClientRequestToken != null) + json.WriteString("ClientRequestToken", _request.ClientRequestToken); if (_request.ReturnConsumedCapacity != ReturnConsumedCapacity.None) json.WriteReturnConsumedCapacity(_request.ReturnConsumedCapacity); From 13440521c1de1c0794726b3c47f946576cc21ca0 Mon Sep 17 00:00:00 2001 From: Chris Perez Date: Tue, 1 Oct 2024 13:09:02 -0600 Subject: [PATCH 12/18] include Parameters property only if there are parameters --- .../BatchExecuteStatementRequestHttpContent.cs | 13 ++++++++----- .../ExecuteStatementRequestHttpContent.cs | 13 ++++++++----- .../ExecuteTransactionRequestHttpContent.cs | 13 ++++++++----- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementRequestHttpContent.cs b/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementRequestHttpContent.cs index a0519391..5cfa494b 100644 --- a/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementRequestHttpContent.cs +++ b/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementRequestHttpContent.cs @@ -29,13 +29,16 @@ protected override ValueTask WriteDataAsync(DdbWriter writer) json.WriteString("Statement", statementRequest.Statement); - json.WritePropertyName("Parameters"); - json.WriteStartArray(); - foreach (var parameter in statementRequest.Parameters) + if (statementRequest.Parameters.Count > 0) { - parameter.Write(json); + json.WritePropertyName("Parameters"); + json.WriteStartArray(); + foreach (var parameter in statementRequest.Parameters) + { + parameter.Write(json); + } + json.WriteEndArray(); } - json.WriteEndArray(); if (statementRequest.ConsistentRead) json.WriteBoolean("ConsistentRead", true); diff --git a/src/EfficientDynamoDb/Internal/Operations/ExecuteStatement/ExecuteStatementRequestHttpContent.cs b/src/EfficientDynamoDb/Internal/Operations/ExecuteStatement/ExecuteStatementRequestHttpContent.cs index 5bb97fc0..0aa0661b 100644 --- a/src/EfficientDynamoDb/Internal/Operations/ExecuteStatement/ExecuteStatementRequestHttpContent.cs +++ b/src/EfficientDynamoDb/Internal/Operations/ExecuteStatement/ExecuteStatementRequestHttpContent.cs @@ -24,13 +24,16 @@ protected override ValueTask WriteDataAsync(DdbWriter writer) json.WritePropertyName("Statement"); json.WriteStringValue(_request.Statement); - json.WritePropertyName("Parameters"); - json.WriteStartArray(); - foreach (var parameter in _request.Parameters) + if (_request.Parameters.Count > 0) { - parameter.Write(json); + json.WritePropertyName("Parameters"); + json.WriteStartArray(); + foreach (var parameter in _request.Parameters) + { + parameter.Write(json); + } + json.WriteEndArray(); } - json.WriteEndArray(); if (_request.ConsistentRead) json.WriteBoolean("ConsistentRead", true); diff --git a/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionRequestHttpContent.cs b/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionRequestHttpContent.cs index d93fa1d1..2bf4efc6 100644 --- a/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionRequestHttpContent.cs +++ b/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionRequestHttpContent.cs @@ -29,13 +29,16 @@ protected override ValueTask WriteDataAsync(DdbWriter writer) json.WriteString("Statement", statement.Statement); - json.WritePropertyName("Parameters"); - json.WriteStartArray(); - foreach (var parameter in statement.Parameters) + if (statement.Parameters.Count > 0) { - parameter.Write(json); + json.WritePropertyName("Parameters"); + json.WriteStartArray(); + foreach (var parameter in statement.Parameters) + { + parameter.Write(json); + } + json.WriteEndArray(); } - json.WriteEndArray(); json.WriteEndObject(); } From 5e30b60a625a6f1a2284ed4004cd1b6a8df38008 Mon Sep 17 00:00:00 2001 From: Chris Perez Date: Tue, 1 Oct 2024 13:16:48 -0600 Subject: [PATCH 13/18] suppress the nullability --- .../BatchExecuteStatement/BatchExecuteStatementResponse.cs | 2 +- .../Operations/ExecuteStatement/ExecuteStatementResponse.cs | 2 +- .../Operations/ExecuteTransaction/ExecuteTransactionResponse.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementResponse.cs b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementResponse.cs index 6e16e8dc..04ee3fa9 100644 --- a/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementResponse.cs +++ b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementResponse.cs @@ -13,7 +13,7 @@ public class BatchExecuteStatementResponse /// according to the ordering of the request statements. /// /// - public IReadOnlyList? Responses { get; set; } + public IReadOnlyList Responses { get; set; } = null!; /// /// Gets and sets the property ConsumedCapacity. diff --git a/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementResponse.cs b/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementResponse.cs index b684003f..ea447464 100644 --- a/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementResponse.cs +++ b/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementResponse.cs @@ -14,7 +14,7 @@ public class ExecuteStatementResponse /// be empty. /// /// - public IReadOnlyList? Items { get; set; } + public IReadOnlyList Items { get; set; } = null!; /// /// Gets and sets the property LastEvaluatedKey. diff --git a/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionResponse.cs b/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionResponse.cs index a1141cb2..e395ab06 100644 --- a/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionResponse.cs +++ b/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionResponse.cs @@ -13,7 +13,7 @@ public class ExecuteTransactionResponse /// according to the ordering of the request statements. /// /// - public IReadOnlyList? Responses { get; set; } + public IReadOnlyList Responses { get; set; } = null!; /// /// Gets and sets the property ConsumedCapacity. From a2dd3725602be266f19246e031dad699afe3e81b Mon Sep 17 00:00:00 2001 From: Chris Perez Date: Sun, 6 Oct 2024 15:24:44 -0600 Subject: [PATCH 14/18] add DynamoDbLowLevelPartiQLContext --- .../DynamoDbLowLevelContext.cs | 45 ++++------------- .../DynamoDbLowLevelPartiQLContext.cs | 50 +++++++++++++++++++ .../IDynamoDbLowLevelContext.cs | 15 ++---- .../IDynamoDbLowLevelPartiQLContext.cs | 17 +++++++ 4 files changed, 80 insertions(+), 47 deletions(-) create mode 100644 src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelPartiQLContext.cs create mode 100644 src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelPartiQLContext.cs diff --git a/src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelContext.cs b/src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelContext.cs index 1c92d150..deebe4a6 100644 --- a/src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelContext.cs +++ b/src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelContext.cs @@ -1,19 +1,11 @@ -using System.Collections.Concurrent; -using System.Linq; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; using EfficientDynamoDb.DocumentModel; using EfficientDynamoDb.Exceptions; using EfficientDynamoDb.Internal; using EfficientDynamoDb.Internal.Extensions; -using EfficientDynamoDb.Internal.Operations.BatchExecuteStatement; using EfficientDynamoDb.Internal.Operations.BatchGetItem; using EfficientDynamoDb.Internal.Operations.BatchWriteItem; using EfficientDynamoDb.Internal.Operations.DeleteItem; using EfficientDynamoDb.Internal.Operations.DescribeTable; -using EfficientDynamoDb.Internal.Operations.ExecuteStatement; -using EfficientDynamoDb.Internal.Operations.ExecuteTransaction; using EfficientDynamoDb.Internal.Operations.GetItem; using EfficientDynamoDb.Internal.Operations.PutItem; using EfficientDynamoDb.Internal.Operations.Query; @@ -22,14 +14,11 @@ using EfficientDynamoDb.Internal.Operations.TransactWriteItems; using EfficientDynamoDb.Internal.Operations.UpdateItem; using EfficientDynamoDb.Internal.Reader; -using EfficientDynamoDb.Operations.BatchExecuteStatement; using EfficientDynamoDb.Operations.BatchGetItem; using EfficientDynamoDb.Operations.BatchWriteItem; using EfficientDynamoDb.Operations.DeleteItem; using EfficientDynamoDb.Operations.DescribeTable; using EfficientDynamoDb.Operations.DescribeTable.Models.Enums; -using EfficientDynamoDb.Operations.ExecuteStatement; -using EfficientDynamoDb.Operations.ExecuteTransaction; using EfficientDynamoDb.Operations.GetItem; using EfficientDynamoDb.Operations.PutItem; using EfficientDynamoDb.Operations.Query; @@ -37,6 +26,11 @@ using EfficientDynamoDb.Operations.TransactGetItems; using EfficientDynamoDb.Operations.TransactWriteItems; using EfficientDynamoDb.Operations.UpdateItem; +using System.Collections.Concurrent; +using System.Linq; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; namespace EfficientDynamoDb { @@ -45,11 +39,14 @@ public class DynamoDbLowLevelContext : IDynamoDbLowLevelContext internal DynamoDbContextConfig Config { get; } internal HttpApi Api { get; } private static readonly ConcurrentDictionary> KeysCache = new ConcurrentDictionary>(); - + private readonly DynamoDbLowLevelPartiQLContext _partiQLContext; + public IDynamoDbLowLevelPartiQLContext PartiQL => _partiQLContext; + internal DynamoDbLowLevelContext(DynamoDbContextConfig config, HttpApi api) { Api = api; Config = config; + _partiQLContext = new DynamoDbLowLevelPartiQLContext(config, api); } public async Task GetItemAsync(GetItemRequest request, CancellationToken cancellationToken = default) @@ -152,30 +149,6 @@ public async Task TransactWriteItemsAsync(TransactWr return TransactWriteItemsResponseParser.Parse(result); } - public async Task ExecuteStatementAsync(ExecuteStatementRequest request, CancellationToken cancellationToken = default) - { - var httpContent = new ExecuteStatementRequestHttpContent(request); - using var response = await Api.SendAsync(Config, httpContent, cancellationToken).ConfigureAwait(false); - var result = await ReadDocumentAsync(response, QueryParsingOptions.Instance, cancellationToken).ConfigureAwait(false); - return ExecuteStatementResponseParser.Parse(result!); - } - - public async Task BatchExecuteStatementAsync(BatchExecuteStatementRequest request, CancellationToken cancellationToken = default) - { - var httpContent = new BatchExecuteStatementRequestHttpContent(request); - using var response = await Api.SendAsync(Config, httpContent, cancellationToken).ConfigureAwait(false); - var result = await ReadDocumentAsync(response, QueryParsingOptions.Instance, cancellationToken).ConfigureAwait(false); - return BatchExecuteStatementResponseParser.Parse(result!); - } - - public async Task ExecuteTransactionAsync(ExecuteTransactionRequest request, CancellationToken cancellationToken = default) - { - var httpContent = new ExecuteTransactionRequestHttpContent(request); - using var response = await Api.SendAsync(Config, httpContent, cancellationToken).ConfigureAwait(false); - var result = await ReadDocumentAsync(response, QueryParsingOptions.Instance, cancellationToken).ConfigureAwait(false); - return ExecuteTransactionResponseParser.Parse(result!); - } - public T ToObject(Document document) where T : class => document.ToObject(Config.Metadata); public Document ToDocument(T entity) where T : class => entity.ToDocument(Config.Metadata); diff --git a/src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelPartiQLContext.cs b/src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelPartiQLContext.cs new file mode 100644 index 00000000..c669413b --- /dev/null +++ b/src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelPartiQLContext.cs @@ -0,0 +1,50 @@ +using EfficientDynamoDb.Internal; +using EfficientDynamoDb.Internal.Operations.BatchExecuteStatement; +using EfficientDynamoDb.Internal.Operations.ExecuteStatement; +using EfficientDynamoDb.Internal.Operations.ExecuteTransaction; +using EfficientDynamoDb.Internal.Operations.Query; +using EfficientDynamoDb.Internal.Operations.TransactGetItems; +using EfficientDynamoDb.Operations.BatchExecuteStatement; +using EfficientDynamoDb.Operations.ExecuteStatement; +using EfficientDynamoDb.Operations.ExecuteTransaction; +using System.Threading; +using System.Threading.Tasks; + +namespace EfficientDynamoDb +{ + internal class DynamoDbLowLevelPartiQLContext : IDynamoDbLowLevelPartiQLContext + { + internal DynamoDbContextConfig Config { get; } + internal HttpApi Api { get; } + + internal DynamoDbLowLevelPartiQLContext(DynamoDbContextConfig config, HttpApi api) + { + Api = api; + Config = config; + } + + public async Task ExecuteStatementAsync(ExecuteStatementRequest request, CancellationToken cancellationToken = default) + { + var httpContent = new ExecuteStatementRequestHttpContent(request); + using var response = await Api.SendAsync(Config, httpContent, cancellationToken).ConfigureAwait(false); + var result = await DynamoDbLowLevelContext.ReadDocumentAsync(response, QueryParsingOptions.Instance, cancellationToken).ConfigureAwait(false); + return ExecuteStatementResponseParser.Parse(result!); + } + + public async Task BatchExecuteStatementAsync(BatchExecuteStatementRequest request, CancellationToken cancellationToken = default) + { + var httpContent = new BatchExecuteStatementRequestHttpContent(request); + using var response = await Api.SendAsync(Config, httpContent, cancellationToken).ConfigureAwait(false); + var result = await DynamoDbLowLevelContext.ReadDocumentAsync(response, TransactGetItemsParsingOptions.Instance, cancellationToken).ConfigureAwait(false); + return BatchExecuteStatementResponseParser.Parse(result!); + } + + public async Task ExecuteTransactionAsync(ExecuteTransactionRequest request, CancellationToken cancellationToken = default) + { + var httpContent = new ExecuteTransactionRequestHttpContent(request); + using var response = await Api.SendAsync(Config, httpContent, cancellationToken).ConfigureAwait(false); + var result = await DynamoDbLowLevelContext.ReadDocumentAsync(response, TransactGetItemsParsingOptions.Instance, cancellationToken).ConfigureAwait(false); + return ExecuteTransactionResponseParser.Parse(result!); + } + } +} diff --git a/src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelContext.cs b/src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelContext.cs index 41d87dd2..398f37ad 100644 --- a/src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelContext.cs +++ b/src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelContext.cs @@ -1,12 +1,7 @@ -using System.Threading; -using System.Threading.Tasks; using EfficientDynamoDb.DocumentModel; -using EfficientDynamoDb.Operations.BatchExecuteStatement; using EfficientDynamoDb.Operations.BatchGetItem; using EfficientDynamoDb.Operations.BatchWriteItem; using EfficientDynamoDb.Operations.DeleteItem; -using EfficientDynamoDb.Operations.ExecuteStatement; -using EfficientDynamoDb.Operations.ExecuteTransaction; using EfficientDynamoDb.Operations.GetItem; using EfficientDynamoDb.Operations.PutItem; using EfficientDynamoDb.Operations.Query; @@ -14,11 +9,15 @@ using EfficientDynamoDb.Operations.TransactGetItems; using EfficientDynamoDb.Operations.TransactWriteItems; using EfficientDynamoDb.Operations.UpdateItem; +using System.Threading; +using System.Threading.Tasks; namespace EfficientDynamoDb { public interface IDynamoDbLowLevelContext { + public IDynamoDbLowLevelPartiQLContext PartiQL { get; } + Task GetItemAsync(GetItemRequest request, CancellationToken cancellationToken = default); Task BatchGetItemAsync(BatchGetItemRequest request, CancellationToken cancellationToken = default); @@ -39,12 +38,6 @@ public interface IDynamoDbLowLevelContext Task TransactWriteItemsAsync(TransactWriteItemsRequest request, CancellationToken cancellationToken = default); - Task ExecuteStatementAsync(ExecuteStatementRequest request, CancellationToken cancellationToken = default); - - Task BatchExecuteStatementAsync(BatchExecuteStatementRequest request, CancellationToken cancellationToken = default); - - Task ExecuteTransactionAsync(ExecuteTransactionRequest request, CancellationToken cancellationToken = default); - T ToObject(Document document) where T : class; Document ToDocument(T entity) where T : class; diff --git a/src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelPartiQLContext.cs b/src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelPartiQLContext.cs new file mode 100644 index 00000000..328d45db --- /dev/null +++ b/src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelPartiQLContext.cs @@ -0,0 +1,17 @@ +using EfficientDynamoDb.Operations.BatchExecuteStatement; +using EfficientDynamoDb.Operations.ExecuteStatement; +using EfficientDynamoDb.Operations.ExecuteTransaction; +using System.Threading; +using System.Threading.Tasks; + +namespace EfficientDynamoDb +{ + public interface IDynamoDbLowLevelPartiQLContext + { + Task ExecuteStatementAsync(ExecuteStatementRequest request, CancellationToken cancellationToken = default); + + Task BatchExecuteStatementAsync(BatchExecuteStatementRequest request, CancellationToken cancellationToken = default); + + Task ExecuteTransactionAsync(ExecuteTransactionRequest request, CancellationToken cancellationToken = default); + } +} From 7b6f0a6cae7042b3b09ef353c939173b815ad476 Mon Sep 17 00:00:00 2001 From: Chris Perez Date: Mon, 7 Oct 2024 17:07:44 -0600 Subject: [PATCH 15/18] Refactored BatchExecuteStatementResponse and BatchExecuteStatementResponseParser classes --- .../BatchExecuteStatementResponseParser.cs | 70 ++++++++++++++++--- .../BatchExecuteStatementResponse.cs | 20 +++++- 2 files changed, 78 insertions(+), 12 deletions(-) diff --git a/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementResponseParser.cs b/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementResponseParser.cs index 75913e24..6f4bc95d 100644 --- a/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementResponseParser.cs +++ b/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementResponseParser.cs @@ -1,28 +1,76 @@ using EfficientDynamoDb.DocumentModel; using EfficientDynamoDb.Internal.Operations.Shared; using EfficientDynamoDb.Operations.BatchExecuteStatement; -using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; namespace EfficientDynamoDb.Internal.Operations.BatchExecuteStatement { internal static class BatchExecuteStatementResponseParser { public static BatchExecuteStatementResponse Parse(Document response) + => new BatchExecuteStatementResponse { Responses = ParseResponses(response), ConsumedCapacity = CapacityParser.ParseFullConsumedCapacities(response) }; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static List ParseResponses(Document response) + { + if (!response.TryGetValue("Responses", out var responsesAttr)) + return null!; + + var responsesList = new List(); + + foreach (var item in responsesAttr.AsListAttribute().Items) + { + responsesList.Add(ParseBatchStatementResponse(item.AsDocument())); + } + + return responsesList; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static BatchStatementResponse ParseBatchStatementResponse(Document document) + { + var response = new BatchStatementResponse(); + + if (document.TryGetValue("TableName", out var tableNameAttr)) + { + response.TableName = tableNameAttr.AsString(); + } + + if (document.TryGetValue("Error", out var errorAttr)) + { + response.Error = ParseBatchStatementError(errorAttr.AsDocument()); + } + + if (document.TryGetValue("Item", out var itemAttr)) + { + response.Item = itemAttr.AsDocument(); + } + + return response; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static BatchStatementError? ParseBatchStatementError(Document document) { - var responsesArray = response.TryGetValue("Responses", out var responsesAttribute) - ? (IReadOnlyList)responsesAttribute.AsListAttribute().Items - : Array.Empty(); + var error = new BatchStatementError(); - var items = new Document[responsesArray.Count]; - for (var i = 0; i < responsesArray.Count; i++) - items[i] = responsesArray[i].AsDocument()["Item"].AsDocument(); + if (document.TryGetValue("Code", out var codeAttr)) + { + error.Code = codeAttr.AsString(); + } - return new BatchExecuteStatementResponse + if (document.TryGetValue("Message", out var messageAttr)) { - Responses = items, - ConsumedCapacity = CapacityParser.ParseFullConsumedCapacities(response) - }; + error.Message = messageAttr.AsString(); + } + + if (document.TryGetValue("Item", out var itemAttr)) + { + error.Item = itemAttr.AsDocument(); + } + + return error; } } } diff --git a/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementResponse.cs b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementResponse.cs index 04ee3fa9..251d9774 100644 --- a/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementResponse.cs +++ b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementResponse.cs @@ -13,7 +13,7 @@ public class BatchExecuteStatementResponse /// according to the ordering of the request statements. /// /// - public IReadOnlyList Responses { get; set; } = null!; + public IReadOnlyList Responses { get; set; } = null!; /// /// Gets and sets the property ConsumedCapacity. @@ -24,4 +24,22 @@ public class BatchExecuteStatementResponse /// public IReadOnlyList? ConsumedCapacity { get; set; } } + + public class BatchStatementResponse + { + public BatchStatementError? Error { get; set; } + + public Document? Item { get; set; } + + public string? TableName { get; set; } + } + + public class BatchStatementError + { + public string? Code { get; set; } + + public string? Message { get; set; } + + public Document? Item { get; set; } + } } From f880df9fc436febfc531ce769f14ffc454dc7dd0 Mon Sep 17 00:00:00 2001 From: Chris Perez Date: Mon, 7 Oct 2024 17:08:07 -0600 Subject: [PATCH 16/18] Refactored ExecuteTransactionResponse and ExecuteTransactionResponseParser classes --- .../ExecuteTransactionResponseParser.cs | 33 ++++++++++++------- .../ExecuteTransactionResponse.cs | 8 ++++- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionResponseParser.cs b/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionResponseParser.cs index 9ce9e5be..cd93ce14 100644 --- a/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionResponseParser.cs +++ b/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionResponseParser.cs @@ -1,28 +1,39 @@ using EfficientDynamoDb.DocumentModel; using EfficientDynamoDb.Internal.Operations.Shared; using EfficientDynamoDb.Operations.ExecuteTransaction; -using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; namespace EfficientDynamoDb.Internal.Operations.ExecuteTransaction { internal static class ExecuteTransactionResponseParser { public static ExecuteTransactionResponse Parse(Document response) + => new ExecuteTransactionResponse { Responses = ParseResponses(response), ConsumedCapacity = CapacityParser.ParseFullConsumedCapacities(response) }; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static List ParseResponses(Document response) { - var responsesArray = response.TryGetValue("Responses", out var responsesAttribute) - ? (IReadOnlyList)responsesAttribute.AsListAttribute().Items - : Array.Empty(); + if (!response.TryGetValue("Responses", out var responsesAttr)) + return null!; - var items = new Document[responsesArray.Count]; - for (var i = 0; i < responsesArray.Count; i++) - items[i] = responsesArray[i].AsDocument()["Item"].AsDocument(); + var responsesList = new List(); - return new ExecuteTransactionResponse + foreach (var item in responsesAttr.AsListAttribute().Items) { - Responses = items, - ConsumedCapacity = CapacityParser.ParseFullConsumedCapacities(response) - }; + responsesList.Add(ParseItemResponse(item.AsDocument())); + } + + return responsesList; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static ItemResponse ParseItemResponse(Document document) + { + var response = new ItemResponse(); + document.TryGetValue("Item", out var itemAttr); + response.Item = itemAttr.AsDocument(); + return response; } } } diff --git a/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionResponse.cs b/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionResponse.cs index e395ab06..84b68aa7 100644 --- a/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionResponse.cs +++ b/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionResponse.cs @@ -1,4 +1,5 @@ using EfficientDynamoDb.DocumentModel; +using EfficientDynamoDb.Operations.BatchExecuteStatement; using EfficientDynamoDb.Operations.Shared.Capacity; using System.Collections.Generic; @@ -13,7 +14,7 @@ public class ExecuteTransactionResponse /// according to the ordering of the request statements. /// /// - public IReadOnlyList Responses { get; set; } = null!; + public IReadOnlyList Responses { get; set; } = null!; /// /// Gets and sets the property ConsumedCapacity. @@ -24,4 +25,9 @@ public class ExecuteTransactionResponse /// public IReadOnlyList? ConsumedCapacity { get; set; } } + + public class ItemResponse + { + public Document? Item { get; set; } + } } From 61a933a7ba64b0ea5285571ea31bc2cb852e6b90 Mon Sep 17 00:00:00 2001 From: Chris Perez Date: Sun, 13 Oct 2024 15:59:24 -0600 Subject: [PATCH 17/18] return BatchStatementResponse array --- .../BatchExecuteStatementResponseParser.cs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementResponseParser.cs b/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementResponseParser.cs index 6f4bc95d..7f1eeca2 100644 --- a/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementResponseParser.cs +++ b/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementResponseParser.cs @@ -1,7 +1,7 @@ using EfficientDynamoDb.DocumentModel; using EfficientDynamoDb.Internal.Operations.Shared; using EfficientDynamoDb.Operations.BatchExecuteStatement; -using System.Collections.Generic; +using System; using System.Runtime.CompilerServices; namespace EfficientDynamoDb.Internal.Operations.BatchExecuteStatement @@ -12,19 +12,17 @@ public static BatchExecuteStatementResponse Parse(Document response) => new BatchExecuteStatementResponse { Responses = ParseResponses(response), ConsumedCapacity = CapacityParser.ParseFullConsumedCapacities(response) }; [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static List ParseResponses(Document response) + private static BatchStatementResponse[] ParseResponses(Document response) { if (!response.TryGetValue("Responses", out var responsesAttr)) - return null!; + return Array.Empty(); - var responsesList = new List(); + var attributesList = responsesAttr.AsListAttribute().Items; + var responses = new BatchStatementResponse[attributesList.Count]; + for (var i = 0; i < attributesList.Count; i++) + responses[i] = ParseBatchStatementResponse(attributesList[i].AsDocument()); - foreach (var item in responsesAttr.AsListAttribute().Items) - { - responsesList.Add(ParseBatchStatementResponse(item.AsDocument())); - } - - return responsesList; + return responses; } [MethodImpl(MethodImplOptions.AggressiveInlining)] From f475143ddc3c3b9e68851da5493d1d4638499124 Mon Sep 17 00:00:00 2001 From: Chris Perez Date: Sun, 13 Oct 2024 15:59:36 -0600 Subject: [PATCH 18/18] return ItemResponse array --- .../ExecuteTransactionResponseParser.cs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionResponseParser.cs b/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionResponseParser.cs index cd93ce14..1bd16035 100644 --- a/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionResponseParser.cs +++ b/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionResponseParser.cs @@ -1,7 +1,7 @@ using EfficientDynamoDb.DocumentModel; using EfficientDynamoDb.Internal.Operations.Shared; using EfficientDynamoDb.Operations.ExecuteTransaction; -using System.Collections.Generic; +using System; using System.Runtime.CompilerServices; namespace EfficientDynamoDb.Internal.Operations.ExecuteTransaction @@ -12,19 +12,17 @@ public static ExecuteTransactionResponse Parse(Document response) => new ExecuteTransactionResponse { Responses = ParseResponses(response), ConsumedCapacity = CapacityParser.ParseFullConsumedCapacities(response) }; [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static List ParseResponses(Document response) + private static ItemResponse[] ParseResponses(Document response) { if (!response.TryGetValue("Responses", out var responsesAttr)) - return null!; + return Array.Empty(); - var responsesList = new List(); + var attributesList = responsesAttr.AsListAttribute().Items; + var responses = new ItemResponse[attributesList.Count]; + for (var i = 0; i < attributesList.Count; i++) + responses[i] = ParseItemResponse(attributesList[i].AsDocument()); - foreach (var item in responsesAttr.AsListAttribute().Items) - { - responsesList.Add(ParseItemResponse(item.AsDocument())); - } - - return responsesList; + return responses; } [MethodImpl(MethodImplOptions.AggressiveInlining)]