public async Task <TRecord?> ExecuteReturnNewItemAsync(CancellationToken cancellationToken)
        {
            PrepareRequest();
            _request.ReturnValues = ReturnValue.ALL_NEW;
            try {
                var response = await _table.DynamoClient.UpdateItemAsync(_request);

                return(_table.DeserializeItem <TRecord>(response.Attributes));
            } catch (ConditionalCheckFailedException) {
                return(default(TRecord));
            }
        }
Example #2
0
        public async Task <(bool Success, IEnumerable <TRecord> Items)> TryExecuteAsync(int maxAttempts = 5, CancellationToken cancellationToken = default)
        {
            if (!_request.TransactItems.Any())
            {
                throw new ArgumentException("primary keys cannot be empty");
            }
            if (_request.TransactItems.Count > 25)
            {
                throw new ArgumentException("too many primary keys");
            }
            for (var i = 0; i < _request.TransactItems.Count; ++i)
            {
                _request.TransactItems[i].Get.ProjectionExpression = _converters[i].ConvertProjections();
            }

            // perform transaction
            try {
                var result   = new List <TRecord>();
                var response = await _table.DynamoClient.TransactGetItemsAsync(_request, cancellationToken);

                foreach (var itemResponse in response.Responses)
                {
                    var record = _table.DeserializeItem <TRecord>(itemResponse.Item);
                    if (!(record is null))
                    {
                        result.Add(record);
                    }
                }
                return(Success : true, Items : result);
            } catch (TransactionCanceledException) {
                // transaction failed
                return(Success : false, Items : Enumerable.Empty <TRecord>());
            }
        }
Example #3
0
        public async Task <TRecord?> ExecuteAsync(CancellationToken cancellationToken)
        {
            _request.ProjectionExpression = _converter.ConvertProjections();
            var response = await _table.DynamoClient.GetItemAsync(_request, cancellationToken);

            return(response.IsItemSet
                ? _table.DeserializeItem <TRecord>(response.Item)
                : null);
        }
Example #4
0
        public async Task <TRecord?> ExecuteReturnOldItemAsync(CancellationToken cancellationToken)
        {
            _request.ConditionExpression = _converter.ConvertConditions(_table.Options);
            _request.ReturnValues        = ReturnValue.ALL_OLD;
            try {
                var response = await _table.DynamoClient.DeleteItemAsync(_request);

                return(_table.DeserializeItem <TRecord>(response.Attributes));
            } catch (ConditionalCheckFailedException) {
                return(default(TRecord));
            }
        }
        public async Task <IEnumerable <TRecord> > ExecuteAsync(int maxAttempts, CancellationToken cancellationToken = default)
        {
            var requestTableAndKeys = _request.RequestItems.First();

            requestTableAndKeys.Value.ProjectionExpression = _converter.ConvertProjections();

            // NOTE (2021-06-30, bjorg): batch operations may run out of capacity/bandwidth and may have to be completed in batches themselves
            var result   = new List <TRecord>();
            var attempts = 1;

            do
            {
                try {
                    var response = await _table.DynamoClient.BatchGetItemAsync(_request, cancellationToken);

                    if (response.Responses.Any())
                    {
                        foreach (var item in response.Responses.Single().Value)
                        {
                            var record = _table.DeserializeItem <TRecord>(item);
                            if (!(record is null))
                            {
                                result.Add(record);
                            }
                        }
                    }

                    // check if all requested primary keys were processed
                    if (!response.UnprocessedKeys.Any())
                    {
                        break;
                    }

                    // repeat request with unprocessed primary keys
                    requestTableAndKeys.Value.Keys = response.UnprocessedKeys.First().Value.Keys;
                } catch (ProvisionedThroughputExceededException) {
                    // NOTE (2021-06-30, bjorg): not a single item could be returned due to insufficient read capacity
                }

                // use exponential backoff before attempting next operation
                if (attempts >= maxAttempts)
                {
                    throw new DynamoTableBatchGetItemsMaxAttemptsExceededException(result);
                }
                await Task.Delay(TimeSpan.FromMilliseconds(MILLISECOND_BACKOFF << (attempts++ - 1)));
            } while(true);
            return(result);
        }